UIRender.cpp 90 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200
  1. #include "StdAfx.h"
  2. ///////////////////////////////////////////////////////////////////////////////////////
  3. DECLARE_HANDLE(HZIP); // An HZIP identifies a zip file that has been opened
  4. typedef DWORD ZRESULT;
  5. typedef struct
  6. {
  7. int index; // index of this file within the zip
  8. char name[MAX_PATH]; // filename within the zip
  9. DWORD attr; // attributes, as in GetFileAttributes.
  10. FILETIME atime,ctime,mtime;// access, create, modify filetimes
  11. long comp_size; // sizes of item, compressed and uncompressed. These
  12. long unc_size; // may be -1 if not yet known (e.g. being streamed in)
  13. } ZIPENTRY;
  14. typedef struct
  15. {
  16. int index; // index of this file within the zip
  17. TCHAR name[MAX_PATH]; // filename within the zip
  18. DWORD attr; // attributes, as in GetFileAttributes.
  19. FILETIME atime,ctime,mtime;// access, create, modify filetimes
  20. long comp_size; // sizes of item, compressed and uncompressed. These
  21. long unc_size; // may be -1 if not yet known (e.g. being streamed in)
  22. } ZIPENTRYW;
  23. #define OpenZip OpenZipU
  24. #define CloseZip(hz) CloseZipU(hz)
  25. extern HZIP OpenZipU(void *z,unsigned int len,DWORD flags);
  26. extern ZRESULT CloseZipU(HZIP hz);
  27. #ifdef _UNICODE
  28. #define ZIPENTRY ZIPENTRYW
  29. #define GetZipItem GetZipItemW
  30. #define FindZipItem FindZipItemW
  31. #else
  32. #define GetZipItem GetZipItemA
  33. #define FindZipItem FindZipItemA
  34. #endif
  35. extern ZRESULT GetZipItemA(HZIP hz, int index, ZIPENTRY *ze);
  36. extern ZRESULT GetZipItemW(HZIP hz, int index, ZIPENTRYW *ze);
  37. extern ZRESULT FindZipItemA(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRY *ze);
  38. extern ZRESULT FindZipItemW(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRYW *ze);
  39. extern ZRESULT UnzipItem(HZIP hz, int index, void *dst, unsigned int len, DWORD flags);
  40. ///////////////////////////////////////////////////////////////////////////////////////
  41. #define RES_TYPE_COLOR _T("*COLOR*")
  42. extern "C"
  43. {
  44. extern unsigned char *stbi_load_from_memory(unsigned char const *buffer, int len, int *x, int *y, \
  45. int *comp, int req_comp);
  46. extern void stbi_image_free(void *retval_from_stbi_load);
  47. };
  48. namespace DuiLib {
  49. static int g_iFontID = MAX_FONT_ID;
  50. /////////////////////////////////////////////////////////////////////////////////////
  51. //
  52. //
  53. CRenderClip::~CRenderClip()
  54. {
  55. ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
  56. ASSERT(::GetObjectType(hRgn)==OBJ_REGION);
  57. ASSERT(::GetObjectType(hOldRgn)==OBJ_REGION);
  58. ::SelectClipRgn(hDC, hOldRgn);
  59. ::DeleteObject(hOldRgn);
  60. ::DeleteObject(hRgn);
  61. }
  62. void CRenderClip::GenerateClip(HDC hDC, RECT rc, CRenderClip& clip)
  63. {
  64. RECT rcClip = { 0 };
  65. ::GetClipBox(hDC, &rcClip);
  66. clip.hOldRgn = ::CreateRectRgnIndirect(&rcClip);
  67. clip.hRgn = ::CreateRectRgnIndirect(&rc);
  68. ::CombineRgn(clip.hRgn, clip.hRgn, clip.hOldRgn, RGN_AND);
  69. ::SelectClipRgn(hDC, clip.hRgn);
  70. clip.hDC = hDC;
  71. clip.rcItem = rc;
  72. }
  73. void CRenderClip::GenerateRoundClip(HDC hDC, RECT rc, RECT rcItem, int width, int height, CRenderClip& clip)
  74. {
  75. RECT rcClip = { 0 };
  76. ::GetClipBox(hDC, &rcClip);
  77. clip.hOldRgn = ::CreateRectRgnIndirect(&rcClip);
  78. clip.hRgn = ::CreateRectRgnIndirect(&rc);
  79. HRGN hRgnItem = ::CreateRoundRectRgn(rcItem.left, rcItem.top, rcItem.right + 1, rcItem.bottom + 1, width, height);
  80. ::CombineRgn(clip.hRgn, clip.hRgn, hRgnItem, RGN_AND);
  81. ::CombineRgn(clip.hRgn, clip.hRgn, clip.hOldRgn, RGN_AND);
  82. ::SelectClipRgn(hDC, clip.hRgn);
  83. clip.hDC = hDC;
  84. clip.rcItem = rc;
  85. ::DeleteObject(hRgnItem);
  86. }
  87. void CRenderClip::UseOldClipBegin(HDC hDC, CRenderClip& clip)
  88. {
  89. ::SelectClipRgn(hDC, clip.hOldRgn);
  90. }
  91. void CRenderClip::UseOldClipEnd(HDC hDC, CRenderClip& clip)
  92. {
  93. ::SelectClipRgn(hDC, clip.hRgn);
  94. }
  95. /////////////////////////////////////////////////////////////////////////////////////
  96. //
  97. //
  98. static const float OneThird = 1.0f / 3;
  99. static void RGBtoHSL(DWORD ARGB, float* H, float* S, float* L) {
  100. const float
  101. R = (float)GetRValue(ARGB),
  102. G = (float)GetGValue(ARGB),
  103. B = (float)GetBValue(ARGB),
  104. nR = (R<0?0:(R>255?255:R))/255,
  105. nG = (G<0?0:(G>255?255:G))/255,
  106. nB = (B<0?0:(B>255?255:B))/255,
  107. m = min(min(nR,nG),nB),
  108. M = max(max(nR,nG),nB);
  109. *L = (m + M)/2;
  110. if (M==m) *H = *S = 0;
  111. else {
  112. const float
  113. f = (nR==m)?(nG-nB):((nG==m)?(nB-nR):(nR-nG)),
  114. i = (nR==m)?3.0f:((nG==m)?5.0f:1.0f);
  115. *H = (i-f/(M-m));
  116. if (*H>=6) *H-=6;
  117. *H*=60;
  118. *S = (2*(*L)<=1)?((M-m)/(M+m)):((M-m)/(2-M-m));
  119. }
  120. }
  121. static void HSLtoRGB(DWORD* ARGB, float H, float S, float L) {
  122. const float
  123. q = 2*L<1?L*(1+S):(L+S-L*S),
  124. p = 2*L-q,
  125. h = H/360,
  126. tr = h + OneThird,
  127. tg = h,
  128. tb = h - OneThird,
  129. ntr = tr<0?tr+1:(tr>1?tr-1:tr),
  130. ntg = tg<0?tg+1:(tg>1?tg-1:tg),
  131. ntb = tb<0?tb+1:(tb>1?tb-1:tb),
  132. B = 255*(6*ntr<1?p+(q-p)*6*ntr:(2*ntr<1?q:(3*ntr<2?p+(q-p)*6*(2.0f*OneThird-ntr):p))),
  133. G = 255*(6*ntg<1?p+(q-p)*6*ntg:(2*ntg<1?q:(3*ntg<2?p+(q-p)*6*(2.0f*OneThird-ntg):p))),
  134. R = 255*(6*ntb<1?p+(q-p)*6*ntb:(2*ntb<1?q:(3*ntb<2?p+(q-p)*6*(2.0f*OneThird-ntb):p)));
  135. *ARGB &= 0xFF000000;
  136. *ARGB |= RGB( (BYTE)(R<0?0:(R>255?255:R)), (BYTE)(G<0?0:(G>255?255:G)), (BYTE)(B<0?0:(B>255?255:B)) );
  137. }
  138. static COLORREF PixelAlpha(COLORREF clrSrc, double src_darken, COLORREF clrDest, double dest_darken)
  139. {
  140. return RGB (GetRValue (clrSrc) * src_darken + GetRValue (clrDest) * dest_darken,
  141. GetGValue (clrSrc) * src_darken + GetGValue (clrDest) * dest_darken,
  142. GetBValue (clrSrc) * src_darken + GetBValue (clrDest) * dest_darken);
  143. }
  144. static BOOL WINAPI AlphaBitBlt(HDC hDC, int nDestX, int nDestY, int dwWidth, int dwHeight, HDC hSrcDC, \
  145. int nSrcX, int nSrcY, int wSrc, int hSrc, BLENDFUNCTION ftn)
  146. {
  147. HDC hTempDC = ::CreateCompatibleDC(hDC);
  148. if (NULL == hTempDC)
  149. return FALSE;
  150. //Creates Source DIB
  151. LPBITMAPINFO lpbiSrc = NULL;
  152. // Fill in the BITMAPINFOHEADER
  153. lpbiSrc = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)];
  154. if (lpbiSrc == NULL)
  155. {
  156. ::DeleteDC(hTempDC);
  157. return FALSE;
  158. }
  159. lpbiSrc->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  160. lpbiSrc->bmiHeader.biWidth = dwWidth;
  161. lpbiSrc->bmiHeader.biHeight = dwHeight;
  162. lpbiSrc->bmiHeader.biPlanes = 1;
  163. lpbiSrc->bmiHeader.biBitCount = 32;
  164. lpbiSrc->bmiHeader.biCompression = BI_RGB;
  165. lpbiSrc->bmiHeader.biSizeImage = dwWidth * dwHeight;
  166. lpbiSrc->bmiHeader.biXPelsPerMeter = 0;
  167. lpbiSrc->bmiHeader.biYPelsPerMeter = 0;
  168. lpbiSrc->bmiHeader.biClrUsed = 0;
  169. lpbiSrc->bmiHeader.biClrImportant = 0;
  170. COLORREF* pSrcBits = NULL;
  171. HBITMAP hSrcDib = CreateDIBSection (
  172. hSrcDC, lpbiSrc, DIB_RGB_COLORS, (void **)&pSrcBits,
  173. NULL, NULL);
  174. if ((NULL == hSrcDib) || (NULL == pSrcBits))
  175. {
  176. delete [] lpbiSrc;
  177. ::DeleteDC(hTempDC);
  178. return FALSE;
  179. }
  180. HBITMAP hOldTempBmp = (HBITMAP)::SelectObject (hTempDC, hSrcDib);
  181. ::StretchBlt(hTempDC, 0, 0, dwWidth, dwHeight, hSrcDC, nSrcX, nSrcY, wSrc, hSrc, SRCCOPY);
  182. ::SelectObject (hTempDC, hOldTempBmp);
  183. //Creates Destination DIB
  184. LPBITMAPINFO lpbiDest = NULL;
  185. // Fill in the BITMAPINFOHEADER
  186. lpbiDest = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)];
  187. if (lpbiDest == NULL)
  188. {
  189. delete [] lpbiSrc;
  190. ::DeleteObject(hSrcDib);
  191. ::DeleteDC(hTempDC);
  192. return FALSE;
  193. }
  194. lpbiDest->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  195. lpbiDest->bmiHeader.biWidth = dwWidth;
  196. lpbiDest->bmiHeader.biHeight = dwHeight;
  197. lpbiDest->bmiHeader.biPlanes = 1;
  198. lpbiDest->bmiHeader.biBitCount = 32;
  199. lpbiDest->bmiHeader.biCompression = BI_RGB;
  200. lpbiDest->bmiHeader.biSizeImage = dwWidth * dwHeight;
  201. lpbiDest->bmiHeader.biXPelsPerMeter = 0;
  202. lpbiDest->bmiHeader.biYPelsPerMeter = 0;
  203. lpbiDest->bmiHeader.biClrUsed = 0;
  204. lpbiDest->bmiHeader.biClrImportant = 0;
  205. COLORREF* pDestBits = NULL;
  206. HBITMAP hDestDib = CreateDIBSection (
  207. hDC, lpbiDest, DIB_RGB_COLORS, (void **)&pDestBits,
  208. NULL, NULL);
  209. if ((NULL == hDestDib) || (NULL == pDestBits))
  210. {
  211. delete [] lpbiSrc;
  212. ::DeleteObject(hSrcDib);
  213. ::DeleteDC(hTempDC);
  214. return FALSE;
  215. }
  216. ::SelectObject (hTempDC, hDestDib);
  217. ::BitBlt (hTempDC, 0, 0, dwWidth, dwHeight, hDC, nDestX, nDestY, SRCCOPY);
  218. ::SelectObject (hTempDC, hOldTempBmp);
  219. double src_darken;
  220. BYTE nAlpha;
  221. for (int pixel = 0; pixel < dwWidth * dwHeight; pixel++, pSrcBits++, pDestBits++)
  222. {
  223. nAlpha = LOBYTE(*pSrcBits >> 24);
  224. src_darken = (double) (nAlpha * ftn.SourceConstantAlpha) / 255.0 / 255.0;
  225. if( src_darken < 0.0 ) src_darken = 0.0;
  226. *pDestBits = PixelAlpha(*pSrcBits, src_darken, *pDestBits, 1.0 - src_darken);
  227. } //for
  228. ::SelectObject (hTempDC, hDestDib);
  229. ::BitBlt (hDC, nDestX, nDestY, dwWidth, dwHeight, hTempDC, 0, 0, SRCCOPY);
  230. ::SelectObject (hTempDC, hOldTempBmp);
  231. delete [] lpbiDest;
  232. ::DeleteObject(hDestDib);
  233. delete [] lpbiSrc;
  234. ::DeleteObject(hSrcDib);
  235. ::DeleteDC(hTempDC);
  236. return TRUE;
  237. }
  238. /////////////////////////////////////////////////////////////////////////////////////
  239. //
  240. //
  241. DWORD CRenderEngine::AdjustColor(DWORD dwColor, short H, short S, short L)
  242. {
  243. if( H == 180 && S == 100 && L == 100 ) return dwColor;
  244. float fH, fS, fL;
  245. float S1 = S / 100.0f;
  246. float L1 = L / 100.0f;
  247. RGBtoHSL(dwColor, &fH, &fS, &fL);
  248. fH += (H - 180);
  249. fH = fH > 0 ? fH : fH + 360;
  250. fS *= S1;
  251. fL *= L1;
  252. HSLtoRGB(&dwColor, fH, fS, fL);
  253. return dwColor;
  254. }
  255. HBITMAP CRenderEngine::CreateARGB32Bitmap(HDC hDC, int cx, int cy, COLORREF** pBits)
  256. {
  257. LPBITMAPINFO lpbiSrc = NULL;
  258. lpbiSrc = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)];
  259. if (lpbiSrc == NULL) return NULL;
  260. lpbiSrc->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  261. lpbiSrc->bmiHeader.biWidth = cx;
  262. lpbiSrc->bmiHeader.biHeight = cy;
  263. lpbiSrc->bmiHeader.biPlanes = 1;
  264. lpbiSrc->bmiHeader.biBitCount = 32;
  265. lpbiSrc->bmiHeader.biCompression = BI_RGB;
  266. lpbiSrc->bmiHeader.biSizeImage = cx * cy;
  267. lpbiSrc->bmiHeader.biXPelsPerMeter = 0;
  268. lpbiSrc->bmiHeader.biYPelsPerMeter = 0;
  269. lpbiSrc->bmiHeader.biClrUsed = 0;
  270. lpbiSrc->bmiHeader.biClrImportant = 0;
  271. HBITMAP hBitmap = CreateDIBSection (hDC, lpbiSrc, DIB_RGB_COLORS, (void **)pBits, NULL, NULL);
  272. delete [] lpbiSrc;
  273. return hBitmap;
  274. }
  275. void CRenderEngine::AdjustImage(bool bUseHSL, TImageInfo* imageInfo, short H, short S, short L)
  276. {
  277. if( imageInfo == NULL || imageInfo->bUseHSL == false || imageInfo->hBitmap == NULL ||
  278. imageInfo->pBits == NULL || imageInfo->pSrcBits == NULL )
  279. return;
  280. if( bUseHSL == false || (H == 180 && S == 100 && L == 100)) {
  281. ::CopyMemory(imageInfo->pBits, imageInfo->pSrcBits, imageInfo->nX * imageInfo->nY * 4);
  282. return;
  283. }
  284. float fH, fS, fL;
  285. float S1 = S / 100.0f;
  286. float L1 = L / 100.0f;
  287. for( int i = 0; i < imageInfo->nX * imageInfo->nY; i++ ) {
  288. RGBtoHSL(*(DWORD*)(imageInfo->pSrcBits + i*4), &fH, &fS, &fL);
  289. fH += (H - 180);
  290. fH = fH > 0 ? fH : fH + 360;
  291. fS *= S1;
  292. fL *= L1;
  293. HSLtoRGB((DWORD*)(imageInfo->pBits + i*4), fH, fS, fL);
  294. }
  295. }
  296. TImageInfo* CRenderEngine::LoadImage(STRINGorID bitmap, LPCTSTR type, DWORD mask)
  297. {
  298. LPBYTE pData = NULL;
  299. DWORD dwSize = 0;
  300. do
  301. {
  302. if( type == NULL ) {
  303. CDuiString sFile = CPaintManagerUI::GetResourcePath();
  304. if( CPaintManagerUI::GetResourceZip().IsEmpty() ) {
  305. sFile += bitmap.m_lpstr;
  306. HANDLE hFile = ::CreateFile(sFile.GetData(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, \
  307. FILE_ATTRIBUTE_NORMAL, NULL);
  308. if( hFile == INVALID_HANDLE_VALUE ) break;
  309. dwSize = ::GetFileSize(hFile, NULL);
  310. if (dwSize == 0)
  311. {
  312. ::CloseHandle(hFile);
  313. break;
  314. }
  315. DWORD dwRead = 0;
  316. pData = new BYTE[ dwSize ];
  317. ::ReadFile( hFile, pData, dwSize, &dwRead, NULL );
  318. ::CloseHandle( hFile );
  319. if( dwRead != dwSize ) {
  320. delete[] pData;
  321. pData = NULL;
  322. break;
  323. }
  324. }
  325. else {
  326. sFile += CPaintManagerUI::GetResourceZip();
  327. HZIP hz = NULL;
  328. if( CPaintManagerUI::IsCachedResourceZip() ) hz = (HZIP)CPaintManagerUI::GetResourceZipHandle();
  329. else hz = OpenZip((void*)sFile.GetData(), 0, 2);
  330. if( hz == NULL ) break;
  331. ZIPENTRY ze;
  332. int i;
  333. if( FindZipItem(hz, bitmap.m_lpstr, true, &i, &ze) != 0 ) break;
  334. dwSize = ze.unc_size;
  335. if( dwSize == 0 ) break;
  336. pData = new BYTE[ dwSize ];
  337. int res = UnzipItem(hz, i, pData, dwSize, 3);
  338. if( res != 0x00000000 && res != 0x00000600) {
  339. delete[] pData;
  340. pData = NULL;
  341. if( !CPaintManagerUI::IsCachedResourceZip() ) CloseZip(hz);
  342. break;
  343. }
  344. if( !CPaintManagerUI::IsCachedResourceZip() ) CloseZip(hz);
  345. }
  346. }
  347. else if (_tcscmp(type, RES_TYPE_COLOR) == 0) {
  348. pData = (PBYTE)0x1; /* dummy pointer */
  349. }
  350. else {
  351. HRSRC hResource = ::FindResource(CPaintManagerUI::GetResourceDll(), bitmap.m_lpstr, type);
  352. if( hResource == NULL ) break;
  353. HGLOBAL hGlobal = ::LoadResource(CPaintManagerUI::GetResourceDll(), hResource);
  354. if( hGlobal == NULL ) {
  355. FreeResource(hResource);
  356. break;
  357. }
  358. dwSize = ::SizeofResource(CPaintManagerUI::GetResourceDll(), hResource);
  359. if( dwSize == 0 ) break;
  360. pData = new BYTE[ dwSize ];
  361. ::CopyMemory(pData, (LPBYTE)::LockResource(hGlobal), dwSize);
  362. ::FreeResource(hResource);
  363. }
  364. } while (0);
  365. while (!pData)
  366. {
  367. //读不到图片, 则直接去读取bitmap.m_lpstr指向的路径
  368. HANDLE hFile = ::CreateFile(bitmap.m_lpstr, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, \
  369. FILE_ATTRIBUTE_NORMAL, NULL);
  370. if( hFile == INVALID_HANDLE_VALUE ) break;
  371. dwSize = ::GetFileSize(hFile, NULL);
  372. if (dwSize == 0)
  373. {
  374. ::CloseHandle(hFile);
  375. break;
  376. }
  377. DWORD dwRead = 0;
  378. pData = new BYTE[ dwSize ];
  379. ::ReadFile( hFile, pData, dwSize, &dwRead, NULL );
  380. ::CloseHandle( hFile );
  381. if( dwRead != dwSize ) {
  382. delete[] pData;
  383. pData = NULL;
  384. }
  385. break;
  386. }
  387. if (!pData)
  388. {
  389. //::MessageBox(0, _T("读取图片数据失败!"), _T("抓BUG"), MB_OK);
  390. return NULL;
  391. }
  392. LPBYTE pImage = NULL;
  393. int x = 1, y = 1, n;
  394. if (!type || _tcscmp(type, RES_TYPE_COLOR) != 0) {
  395. pImage = stbi_load_from_memory(pData, dwSize, &x, &y, &n, 4);
  396. delete[] pData;
  397. if( !pImage ) {
  398. //::MessageBox(0, _T("解析图片失败"), _T("抓BUG"), MB_OK);
  399. return NULL;
  400. }
  401. }
  402. BITMAPINFO bmi;
  403. ::ZeroMemory(&bmi, sizeof(BITMAPINFO));
  404. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  405. bmi.bmiHeader.biWidth = x;
  406. bmi.bmiHeader.biHeight = -y;
  407. bmi.bmiHeader.biPlanes = 1;
  408. bmi.bmiHeader.biBitCount = 32;
  409. bmi.bmiHeader.biCompression = BI_RGB;
  410. bmi.bmiHeader.biSizeImage = x * y * 4;
  411. bool bAlphaChannel = false;
  412. LPBYTE pDest = NULL;
  413. HBITMAP hBitmap = ::CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**)&pDest, NULL, 0);
  414. if( !hBitmap ) {
  415. //::MessageBox(0, _T("CreateDIBSection失败"), _T("抓BUG"), MB_OK);
  416. return NULL;
  417. }
  418. BYTE bColorBits[4] = { 0 };
  419. if (type && _tcscmp(type, RES_TYPE_COLOR) == 0) {
  420. LPTSTR pstr = NULL;
  421. LPCTSTR pstrValue = bitmap.m_lpstr;
  422. if (*pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
  423. DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
  424. pImage = (LPBYTE)&clrColor;
  425. /* BGRA -> RGBA */
  426. bColorBits[3] = pImage[3];
  427. bColorBits[2] = pImage[0];
  428. bColorBits[1] = pImage[1];
  429. bColorBits[0] = pImage[2];
  430. pImage = bColorBits;
  431. }
  432. for( int i = 0; i < x * y; i++ )
  433. {
  434. pDest[i*4 + 3] = pImage[i*4 + 3];
  435. if( pDest[i*4 + 3] < 255 )
  436. {
  437. pDest[i*4] = (BYTE)(DWORD(pImage[i*4 + 2])*pImage[i*4 + 3]/255);
  438. pDest[i*4 + 1] = (BYTE)(DWORD(pImage[i*4 + 1])*pImage[i*4 + 3]/255);
  439. pDest[i*4 + 2] = (BYTE)(DWORD(pImage[i*4])*pImage[i*4 + 3]/255);
  440. bAlphaChannel = true;
  441. }
  442. else
  443. {
  444. pDest[i*4] = pImage[i*4 + 2];
  445. pDest[i*4 + 1] = pImage[i*4 + 1];
  446. pDest[i*4 + 2] = pImage[i*4];
  447. }
  448. if( *(DWORD*)(&pDest[i*4]) == mask ) {
  449. pDest[i*4] = (BYTE)0;
  450. pDest[i*4 + 1] = (BYTE)0;
  451. pDest[i*4 + 2] = (BYTE)0;
  452. pDest[i*4 + 3] = (BYTE)0;
  453. bAlphaChannel = true;
  454. }
  455. }
  456. if (!type || _tcscmp(type, RES_TYPE_COLOR) != 0) {
  457. stbi_image_free(pImage);
  458. }
  459. TImageInfo* data = new TImageInfo;
  460. data->hBitmap = hBitmap;
  461. data->pBits = pDest;
  462. data->nX = x;
  463. data->nY = y;
  464. data->bAlpha = bAlphaChannel;
  465. data->bUseHSL = false;
  466. data->pSrcBits = NULL;
  467. return data;
  468. }
  469. void CRenderEngine::FreeImage(TImageInfo* bitmap, bool bDelete)
  470. {
  471. if (bitmap == NULL) return;
  472. if (bitmap->hBitmap) {
  473. ::DeleteObject(bitmap->hBitmap);
  474. bitmap->hBitmap = NULL;
  475. }
  476. if (bitmap->pSrcBits) {
  477. delete[] bitmap->pSrcBits;
  478. bitmap->pSrcBits = NULL;
  479. }
  480. if (bDelete) delete bitmap ;
  481. }
  482. void CRenderEngine::DrawImage(HDC hDC, HBITMAP hBitmap, const RECT& rc, const RECT& rcPaint,
  483. const RECT& rcBmpPart, const RECT& rcScale9, bool bAlpha,
  484. BYTE uFade, bool bHole, bool bTiledX, bool bTiledY)
  485. {
  486. ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
  487. typedef BOOL (WINAPI *LPALPHABLEND)(HDC, int, int, int, int,HDC, int, int, int, int, BLENDFUNCTION);
  488. static LPALPHABLEND lpAlphaBlend = (LPALPHABLEND) ::GetProcAddress(::GetModuleHandle(_T("msimg32.dll")), "AlphaBlend");
  489. if( lpAlphaBlend == NULL ) lpAlphaBlend = AlphaBitBlt;
  490. if( hBitmap == NULL ) return;
  491. HDC hCloneDC = ::CreateCompatibleDC(hDC);
  492. HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(hCloneDC, hBitmap);
  493. ::SetStretchBltMode(hDC, COLORONCOLOR);
  494. RECT rcTemp = {0};
  495. RECT rcDest = {0};
  496. if( lpAlphaBlend && (bAlpha || uFade < 255) ) {
  497. BLENDFUNCTION bf = { AC_SRC_OVER, 0, uFade, AC_SRC_ALPHA };
  498. // middle
  499. if( !bHole ) {
  500. rcDest.left = rc.left + rcScale9.left;
  501. rcDest.top = rc.top + rcScale9.top;
  502. rcDest.right = rc.right - rc.left - rcScale9.left - rcScale9.right;
  503. rcDest.bottom = rc.bottom - rc.top - rcScale9.top - rcScale9.bottom;
  504. rcDest.right += rcDest.left;
  505. rcDest.bottom += rcDest.top;
  506. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  507. if( !bTiledX && !bTiledY ) {
  508. rcDest.right -= rcDest.left;
  509. rcDest.bottom -= rcDest.top;
  510. lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  511. rcBmpPart.left + rcScale9.left, rcBmpPart.top + rcScale9.top, \
  512. rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right, \
  513. rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom, bf);
  514. }
  515. else if( bTiledX && bTiledY ) {
  516. LONG lWidth = rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right;
  517. LONG lHeight = rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom;
  518. int iTimesX = (rcDest.right - rcDest.left + lWidth - 1) / lWidth;
  519. int iTimesY = (rcDest.bottom - rcDest.top + lHeight - 1) / lHeight;
  520. for( int j = 0; j < iTimesY; ++j ) {
  521. LONG lDestTop = rcDest.top + lHeight * j;
  522. LONG lDestBottom = rcDest.top + lHeight * (j + 1);
  523. LONG lDrawHeight = lHeight;
  524. if( lDestBottom > rcDest.bottom ) {
  525. lDrawHeight -= lDestBottom - rcDest.bottom;
  526. lDestBottom = rcDest.bottom;
  527. }
  528. for( int i = 0; i < iTimesX; ++i ) {
  529. LONG lDestLeft = rcDest.left + lWidth * i;
  530. LONG lDestRight = rcDest.left + lWidth * (i + 1);
  531. LONG lDrawWidth = lWidth;
  532. if( lDestRight > rcDest.right ) {
  533. lDrawWidth -= lDestRight - rcDest.right;
  534. lDestRight = rcDest.right;
  535. }
  536. lpAlphaBlend(hDC, rcDest.left + lWidth * i, rcDest.top + lHeight * j,
  537. lDestRight - lDestLeft, lDestBottom - lDestTop, hCloneDC,
  538. rcBmpPart.left + rcScale9.left, rcBmpPart.top + rcScale9.top, lDrawWidth, lDrawHeight, bf);
  539. }
  540. }
  541. }
  542. else if( bTiledX ) {
  543. LONG lWidth = rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right;
  544. int iTimes = (rcDest.right - rcDest.left + lWidth - 1) / lWidth;
  545. for( int i = 0; i < iTimes; ++i ) {
  546. LONG lDestLeft = rcDest.left + lWidth * i;
  547. LONG lDestRight = rcDest.left + lWidth * (i + 1);
  548. LONG lDrawWidth = lWidth;
  549. if( lDestRight > rcDest.right ) {
  550. lDrawWidth -= lDestRight - rcDest.right;
  551. lDestRight = rcDest.right;
  552. }
  553. rcDest.bottom -= rcDest.top;
  554. lpAlphaBlend(hDC, lDestLeft, rcDest.top, lDestRight - lDestLeft, rcDest.bottom,
  555. hCloneDC, rcBmpPart.left + rcScale9.left, rcBmpPart.top + rcScale9.top, \
  556. lDrawWidth, rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom, bf);
  557. }
  558. }
  559. else { // bTiledY
  560. LONG lHeight = rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom;
  561. int iTimes = (rcDest.bottom - rcDest.top + lHeight - 1) / lHeight;
  562. for( int i = 0; i < iTimes; ++i ) {
  563. LONG lDestTop = rcDest.top + lHeight * i;
  564. LONG lDestBottom = rcDest.top + lHeight * (i + 1);
  565. LONG lDrawHeight = lHeight;
  566. if( lDestBottom > rcDest.bottom ) {
  567. lDrawHeight -= lDestBottom - rcDest.bottom;
  568. lDestBottom = rcDest.bottom;
  569. }
  570. rcDest.right -= rcDest.left;
  571. lpAlphaBlend(hDC, rcDest.left, rcDest.top + lHeight * i, rcDest.right, lDestBottom - lDestTop,
  572. hCloneDC, rcBmpPart.left + rcScale9.left, rcBmpPart.top + rcScale9.top, \
  573. rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right, lDrawHeight, bf);
  574. }
  575. }
  576. }
  577. }
  578. // left-top
  579. if( rcScale9.left > 0 && rcScale9.top > 0 ) {
  580. rcDest.left = rc.left;
  581. rcDest.top = rc.top;
  582. rcDest.right = rcScale9.left;
  583. rcDest.bottom = rcScale9.top;
  584. rcDest.right += rcDest.left;
  585. rcDest.bottom += rcDest.top;
  586. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  587. rcDest.right -= rcDest.left;
  588. rcDest.bottom -= rcDest.top;
  589. lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  590. rcBmpPart.left, rcBmpPart.top, rcScale9.left, rcScale9.top, bf);
  591. }
  592. }
  593. // top
  594. if( rcScale9.top > 0 ) {
  595. rcDest.left = rc.left + rcScale9.left;
  596. rcDest.top = rc.top;
  597. rcDest.right = rc.right - rc.left - rcScale9.left - rcScale9.right;
  598. rcDest.bottom = rcScale9.top;
  599. rcDest.right += rcDest.left;
  600. rcDest.bottom += rcDest.top;
  601. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  602. rcDest.right -= rcDest.left;
  603. rcDest.bottom -= rcDest.top;
  604. lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  605. rcBmpPart.left + rcScale9.left, rcBmpPart.top, rcBmpPart.right - rcBmpPart.left - \
  606. rcScale9.left - rcScale9.right, rcScale9.top, bf);
  607. }
  608. }
  609. // right-top
  610. if( rcScale9.right > 0 && rcScale9.top > 0 ) {
  611. rcDest.left = rc.right - rcScale9.right;
  612. rcDest.top = rc.top;
  613. rcDest.right = rcScale9.right;
  614. rcDest.bottom = rcScale9.top;
  615. rcDest.right += rcDest.left;
  616. rcDest.bottom += rcDest.top;
  617. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  618. rcDest.right -= rcDest.left;
  619. rcDest.bottom -= rcDest.top;
  620. lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  621. rcBmpPart.right - rcScale9.right, rcBmpPart.top, rcScale9.right, rcScale9.top, bf);
  622. }
  623. }
  624. // left
  625. if( rcScale9.left > 0 ) {
  626. rcDest.left = rc.left;
  627. rcDest.top = rc.top + rcScale9.top;
  628. rcDest.right = rcScale9.left;
  629. rcDest.bottom = rc.bottom - rc.top - rcScale9.top - rcScale9.bottom;
  630. rcDest.right += rcDest.left;
  631. rcDest.bottom += rcDest.top;
  632. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  633. rcDest.right -= rcDest.left;
  634. rcDest.bottom -= rcDest.top;
  635. lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  636. rcBmpPart.left, rcBmpPart.top + rcScale9.top, rcScale9.left, rcBmpPart.bottom - \
  637. rcBmpPart.top - rcScale9.top - rcScale9.bottom, bf);
  638. }
  639. }
  640. // right
  641. if( rcScale9.right > 0 ) {
  642. rcDest.left = rc.right - rcScale9.right;
  643. rcDest.top = rc.top + rcScale9.top;
  644. rcDest.right = rcScale9.right;
  645. rcDest.bottom = rc.bottom - rc.top - rcScale9.top - rcScale9.bottom;
  646. rcDest.right += rcDest.left;
  647. rcDest.bottom += rcDest.top;
  648. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  649. rcDest.right -= rcDest.left;
  650. rcDest.bottom -= rcDest.top;
  651. lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  652. rcBmpPart.right - rcScale9.right, rcBmpPart.top + rcScale9.top, rcScale9.right, \
  653. rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom, bf);
  654. }
  655. }
  656. // left-bottom
  657. if( rcScale9.left > 0 && rcScale9.bottom > 0 ) {
  658. rcDest.left = rc.left;
  659. rcDest.top = rc.bottom - rcScale9.bottom;
  660. rcDest.right = rcScale9.left;
  661. rcDest.bottom = rcScale9.bottom;
  662. rcDest.right += rcDest.left;
  663. rcDest.bottom += rcDest.top;
  664. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  665. rcDest.right -= rcDest.left;
  666. rcDest.bottom -= rcDest.top;
  667. lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  668. rcBmpPart.left, rcBmpPart.bottom - rcScale9.bottom, rcScale9.left, rcScale9.bottom, bf);
  669. }
  670. }
  671. // bottom
  672. if( rcScale9.bottom > 0 ) {
  673. rcDest.left = rc.left + rcScale9.left;
  674. rcDest.top = rc.bottom - rcScale9.bottom;
  675. rcDest.right = rc.right - rc.left - rcScale9.left - rcScale9.right;
  676. rcDest.bottom = rcScale9.bottom;
  677. rcDest.right += rcDest.left;
  678. rcDest.bottom += rcDest.top;
  679. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  680. rcDest.right -= rcDest.left;
  681. rcDest.bottom -= rcDest.top;
  682. lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  683. rcBmpPart.left + rcScale9.left, rcBmpPart.bottom - rcScale9.bottom, \
  684. rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right, rcScale9.bottom, bf);
  685. }
  686. }
  687. // right-bottom
  688. if( rcScale9.right > 0 && rcScale9.bottom > 0 ) {
  689. rcDest.left = rc.right - rcScale9.right;
  690. rcDest.top = rc.bottom - rcScale9.bottom;
  691. rcDest.right = rcScale9.right;
  692. rcDest.bottom = rcScale9.bottom;
  693. rcDest.right += rcDest.left;
  694. rcDest.bottom += rcDest.top;
  695. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  696. rcDest.right -= rcDest.left;
  697. rcDest.bottom -= rcDest.top;
  698. lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  699. rcBmpPart.right - rcScale9.right, rcBmpPart.bottom - rcScale9.bottom, rcScale9.right, \
  700. rcScale9.bottom, bf);
  701. }
  702. }
  703. }
  704. else
  705. {
  706. if (rc.right - rc.left == rcBmpPart.right - rcBmpPart.left \
  707. && rc.bottom - rc.top == rcBmpPart.bottom - rcBmpPart.top \
  708. && rcScale9.left == 0 && rcScale9.right == 0 && rcScale9.top == 0 && rcScale9.bottom == 0)
  709. {
  710. if( ::IntersectRect(&rcTemp, &rcPaint, &rc) ) {
  711. ::BitBlt(hDC, rcTemp.left, rcTemp.top, rcTemp.right - rcTemp.left, rcTemp.bottom - rcTemp.top, \
  712. hCloneDC, rcBmpPart.left + rcTemp.left - rc.left, rcBmpPart.top + rcTemp.top - rc.top, SRCCOPY);
  713. }
  714. }
  715. else
  716. {
  717. // middle
  718. if( !bHole ) {
  719. rcDest.left = rc.left + rcScale9.left;
  720. rcDest.top = rc.top + rcScale9.top;
  721. rcDest.right = rc.right - rc.left - rcScale9.left - rcScale9.right;
  722. rcDest.bottom = rc.bottom - rc.top - rcScale9.top - rcScale9.bottom;
  723. rcDest.right += rcDest.left;
  724. rcDest.bottom += rcDest.top;
  725. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  726. if( !bTiledX && !bTiledY ) {
  727. rcDest.right -= rcDest.left;
  728. rcDest.bottom -= rcDest.top;
  729. ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  730. rcBmpPart.left + rcScale9.left, rcBmpPart.top + rcScale9.top, \
  731. rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right, \
  732. rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom, SRCCOPY);
  733. }
  734. else if( bTiledX && bTiledY ) {
  735. LONG lWidth = rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right;
  736. LONG lHeight = rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom;
  737. int iTimesX = (rcDest.right - rcDest.left + lWidth - 1) / lWidth;
  738. int iTimesY = (rcDest.bottom - rcDest.top + lHeight - 1) / lHeight;
  739. for( int j = 0; j < iTimesY; ++j ) {
  740. LONG lDestTop = rcDest.top + lHeight * j;
  741. LONG lDestBottom = rcDest.top + lHeight * (j + 1);
  742. LONG lDrawHeight = lHeight;
  743. if( lDestBottom > rcDest.bottom ) {
  744. lDrawHeight -= lDestBottom - rcDest.bottom;
  745. lDestBottom = rcDest.bottom;
  746. }
  747. for( int i = 0; i < iTimesX; ++i ) {
  748. LONG lDestLeft = rcDest.left + lWidth * i;
  749. LONG lDestRight = rcDest.left + lWidth * (i + 1);
  750. LONG lDrawWidth = lWidth;
  751. if( lDestRight > rcDest.right ) {
  752. lDrawWidth -= lDestRight - rcDest.right;
  753. lDestRight = rcDest.right;
  754. }
  755. ::BitBlt(hDC, rcDest.left + lWidth * i, rcDest.top + lHeight * j, \
  756. lDestRight - lDestLeft, lDestBottom - lDestTop, hCloneDC, \
  757. rcBmpPart.left + rcScale9.left, rcBmpPart.top + rcScale9.top, SRCCOPY);
  758. }
  759. }
  760. }
  761. else if( bTiledX ) {
  762. LONG lWidth = rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right;
  763. int iTimes = (rcDest.right - rcDest.left + lWidth - 1) / lWidth;
  764. for( int i = 0; i < iTimes; ++i ) {
  765. LONG lDestLeft = rcDest.left + lWidth * i;
  766. LONG lDestRight = rcDest.left + lWidth * (i + 1);
  767. LONG lDrawWidth = lWidth;
  768. if( lDestRight > rcDest.right ) {
  769. lDrawWidth -= lDestRight - rcDest.right;
  770. lDestRight = rcDest.right;
  771. }
  772. rcDest.bottom -= rcDest.top;
  773. ::StretchBlt(hDC, lDestLeft, rcDest.top, lDestRight - lDestLeft, rcDest.bottom,
  774. hCloneDC, rcBmpPart.left + rcScale9.left, rcBmpPart.top + rcScale9.top, \
  775. lDrawWidth, rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom, SRCCOPY);
  776. }
  777. }
  778. else { // bTiledY
  779. LONG lHeight = rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom;
  780. int iTimes = (rcDest.bottom - rcDest.top + lHeight - 1) / lHeight;
  781. for( int i = 0; i < iTimes; ++i ) {
  782. LONG lDestTop = rcDest.top + lHeight * i;
  783. LONG lDestBottom = rcDest.top + lHeight * (i + 1);
  784. LONG lDrawHeight = lHeight;
  785. if( lDestBottom > rcDest.bottom ) {
  786. lDrawHeight -= lDestBottom - rcDest.bottom;
  787. lDestBottom = rcDest.bottom;
  788. }
  789. rcDest.right -= rcDest.left;
  790. ::StretchBlt(hDC, rcDest.left, rcDest.top + lHeight * i, rcDest.right, lDestBottom - lDestTop,
  791. hCloneDC, rcBmpPart.left + rcScale9.left, rcBmpPart.top + rcScale9.top, \
  792. rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right, lDrawHeight, SRCCOPY);
  793. }
  794. }
  795. }
  796. }
  797. // left-top
  798. if( rcScale9.left > 0 && rcScale9.top > 0 ) {
  799. rcDest.left = rc.left;
  800. rcDest.top = rc.top;
  801. rcDest.right = rcScale9.left;
  802. rcDest.bottom = rcScale9.top;
  803. rcDest.right += rcDest.left;
  804. rcDest.bottom += rcDest.top;
  805. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  806. rcDest.right -= rcDest.left;
  807. rcDest.bottom -= rcDest.top;
  808. ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  809. rcBmpPart.left, rcBmpPart.top, rcScale9.left, rcScale9.top, SRCCOPY);
  810. }
  811. }
  812. // top
  813. if( rcScale9.top > 0 ) {
  814. rcDest.left = rc.left + rcScale9.left;
  815. rcDest.top = rc.top;
  816. rcDest.right = rc.right - rc.left - rcScale9.left - rcScale9.right;
  817. rcDest.bottom = rcScale9.top;
  818. rcDest.right += rcDest.left;
  819. rcDest.bottom += rcDest.top;
  820. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  821. rcDest.right -= rcDest.left;
  822. rcDest.bottom -= rcDest.top;
  823. ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  824. rcBmpPart.left + rcScale9.left, rcBmpPart.top, rcBmpPart.right - rcBmpPart.left - \
  825. rcScale9.left - rcScale9.right, rcScale9.top, SRCCOPY);
  826. }
  827. }
  828. // right-top
  829. if( rcScale9.right > 0 && rcScale9.top > 0 ) {
  830. rcDest.left = rc.right - rcScale9.right;
  831. rcDest.top = rc.top;
  832. rcDest.right = rcScale9.right;
  833. rcDest.bottom = rcScale9.top;
  834. rcDest.right += rcDest.left;
  835. rcDest.bottom += rcDest.top;
  836. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  837. rcDest.right -= rcDest.left;
  838. rcDest.bottom -= rcDest.top;
  839. ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  840. rcBmpPart.right - rcScale9.right, rcBmpPart.top, rcScale9.right, rcScale9.top, SRCCOPY);
  841. }
  842. }
  843. // left
  844. if( rcScale9.left > 0 ) {
  845. rcDest.left = rc.left;
  846. rcDest.top = rc.top + rcScale9.top;
  847. rcDest.right = rcScale9.left;
  848. rcDest.bottom = rc.bottom - rc.top - rcScale9.top - rcScale9.bottom;
  849. rcDest.right += rcDest.left;
  850. rcDest.bottom += rcDest.top;
  851. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  852. rcDest.right -= rcDest.left;
  853. rcDest.bottom -= rcDest.top;
  854. ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  855. rcBmpPart.left, rcBmpPart.top + rcScale9.top, rcScale9.left, rcBmpPart.bottom - \
  856. rcBmpPart.top - rcScale9.top - rcScale9.bottom, SRCCOPY);
  857. }
  858. }
  859. // right
  860. if( rcScale9.right > 0 ) {
  861. rcDest.left = rc.right - rcScale9.right;
  862. rcDest.top = rc.top + rcScale9.top;
  863. rcDest.right = rcScale9.right;
  864. rcDest.bottom = rc.bottom - rc.top - rcScale9.top - rcScale9.bottom;
  865. rcDest.right += rcDest.left;
  866. rcDest.bottom += rcDest.top;
  867. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  868. rcDest.right -= rcDest.left;
  869. rcDest.bottom -= rcDest.top;
  870. ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  871. rcBmpPart.right - rcScale9.right, rcBmpPart.top + rcScale9.top, rcScale9.right, \
  872. rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom, SRCCOPY);
  873. }
  874. }
  875. // left-bottom
  876. if( rcScale9.left > 0 && rcScale9.bottom > 0 ) {
  877. rcDest.left = rc.left;
  878. rcDest.top = rc.bottom - rcScale9.bottom;
  879. rcDest.right = rcScale9.left;
  880. rcDest.bottom = rcScale9.bottom;
  881. rcDest.right += rcDest.left;
  882. rcDest.bottom += rcDest.top;
  883. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  884. rcDest.right -= rcDest.left;
  885. rcDest.bottom -= rcDest.top;
  886. ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  887. rcBmpPart.left, rcBmpPart.bottom - rcScale9.bottom, rcScale9.left, rcScale9.bottom, SRCCOPY);
  888. }
  889. }
  890. // bottom
  891. if( rcScale9.bottom > 0 ) {
  892. rcDest.left = rc.left + rcScale9.left;
  893. rcDest.top = rc.bottom - rcScale9.bottom;
  894. rcDest.right = rc.right - rc.left - rcScale9.left - rcScale9.right;
  895. rcDest.bottom = rcScale9.bottom;
  896. rcDest.right += rcDest.left;
  897. rcDest.bottom += rcDest.top;
  898. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  899. rcDest.right -= rcDest.left;
  900. rcDest.bottom -= rcDest.top;
  901. ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  902. rcBmpPart.left + rcScale9.left, rcBmpPart.bottom - rcScale9.bottom, \
  903. rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right, rcScale9.bottom, SRCCOPY);
  904. }
  905. }
  906. // right-bottom
  907. if( rcScale9.right > 0 && rcScale9.bottom > 0 ) {
  908. rcDest.left = rc.right - rcScale9.right;
  909. rcDest.top = rc.bottom - rcScale9.bottom;
  910. rcDest.right = rcScale9.right;
  911. rcDest.bottom = rcScale9.bottom;
  912. rcDest.right += rcDest.left;
  913. rcDest.bottom += rcDest.top;
  914. if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
  915. rcDest.right -= rcDest.left;
  916. rcDest.bottom -= rcDest.top;
  917. ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
  918. rcBmpPart.right - rcScale9.right, rcBmpPart.bottom - rcScale9.bottom, rcScale9.right, \
  919. rcScale9.bottom, SRCCOPY);
  920. }
  921. }
  922. }
  923. }
  924. ::SelectObject(hCloneDC, hOldBitmap);
  925. ::DeleteDC(hCloneDC);
  926. }
  927. bool CRenderEngine::DrawImage(HDC hDC, CPaintManagerUI* pManager, const RECT& rcItem, const RECT& rcPaint,
  928. TDrawInfo& drawInfo)
  929. {
  930. // 1、aaa.jpg
  931. // 2、file='aaa.jpg' res='' restype='0' dest='0,0,0,0' source='0,0,0,0' scale9='0,0,0,0'
  932. // mask='#FF0000' fade='255' hole='false' xtiled='false' ytiled='false' hsl='false'
  933. if( pManager == NULL ) return true;
  934. if( drawInfo.pImageInfo == NULL ) {
  935. if( drawInfo.bLoaded ) return false;
  936. drawInfo.bLoaded = true;
  937. if( drawInfo.sDrawString.IsEmpty() ) return false;
  938. bool bUseRes = false;
  939. CDuiString sImageName = drawInfo.sDrawString;
  940. CDuiString sImageResType;
  941. DWORD dwMask = 0;
  942. bool bUseHSL = false;
  943. CDuiString sItem;
  944. CDuiString sValue;
  945. LPTSTR pstr = NULL;
  946. LPCTSTR pstrImage = drawInfo.sDrawString.GetData();
  947. while( *pstrImage != _T('\0') ) {
  948. sItem.Empty();
  949. sValue.Empty();
  950. while( *pstrImage > _T('\0') && *pstrImage <= _T(' ') ) pstrImage = ::CharNext(pstrImage);
  951. while( *pstrImage != _T('\0') && *pstrImage != _T('=') && *pstrImage > _T(' ') ) {
  952. LPTSTR pstrTemp = ::CharNext(pstrImage);
  953. while( pstrImage < pstrTemp) {
  954. sItem += *pstrImage++;
  955. }
  956. }
  957. while( *pstrImage > _T('\0') && *pstrImage <= _T(' ') ) pstrImage = ::CharNext(pstrImage);
  958. if( *pstrImage++ != _T('=') ) break;
  959. while( *pstrImage > _T('\0') && *pstrImage <= _T(' ') ) pstrImage = ::CharNext(pstrImage);
  960. if( *pstrImage++ != _T('\'') ) break;
  961. while( *pstrImage != _T('\0') && *pstrImage != _T('\'') ) {
  962. LPTSTR pstrTemp = ::CharNext(pstrImage);
  963. while( pstrImage < pstrTemp) {
  964. sValue += *pstrImage++;
  965. }
  966. }
  967. if( *pstrImage++ != _T('\'') ) break;
  968. if( !sValue.IsEmpty() ) {
  969. if( sItem == _T("file") ) {
  970. sImageName = sValue;
  971. }
  972. else if( sItem == _T("res") ) {
  973. bUseRes = true;
  974. sImageName = sValue;
  975. }
  976. else if( sItem == _T("restype") ) {
  977. sImageResType = sValue;
  978. }
  979. else if (sItem == _T("color")) {
  980. bUseRes = true;
  981. sImageResType = RES_TYPE_COLOR;
  982. sImageName = sValue;
  983. }
  984. else if( sItem == _T("dest") ) {
  985. drawInfo.rcDestOffset.left = _tcstol(sValue.GetData(), &pstr, 10); ASSERT(pstr);
  986. drawInfo.rcDestOffset.top = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  987. drawInfo.rcDestOffset.right = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  988. drawInfo.rcDestOffset.bottom = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  989. }
  990. else if( sItem == _T("source") ) {
  991. drawInfo.rcBmpPart.left = _tcstol(sValue.GetData(), &pstr, 10); ASSERT(pstr);
  992. drawInfo.rcBmpPart.top = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  993. drawInfo.rcBmpPart.right = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  994. drawInfo.rcBmpPart.bottom = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  995. }
  996. else if( sItem == _T("corner") || sItem == _T("scale9")) {
  997. drawInfo.rcScale9.left = _tcstol(sValue.GetData(), &pstr, 10); ASSERT(pstr);
  998. drawInfo.rcScale9.top = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  999. drawInfo.rcScale9.right = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  1000. drawInfo.rcScale9.bottom = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  1001. }
  1002. else if( sItem == _T("mask") ) {
  1003. if( sValue[0] == _T('#')) dwMask = _tcstoul(sValue.GetData() + 1, &pstr, 16);
  1004. else dwMask = _tcstoul(sValue.GetData(), &pstr, 16);
  1005. }
  1006. else if( sItem == _T("fade") ) {
  1007. drawInfo.uFade = (BYTE)_tcstoul(sValue.GetData(), &pstr, 10);
  1008. }
  1009. else if( sItem == _T("hole") ) {
  1010. drawInfo.bHole = (_tcscmp(sValue.GetData(), _T("true")) == 0);
  1011. }
  1012. else if( sItem == _T("xtiled") ) {
  1013. drawInfo.bTiledX = (_tcscmp(sValue.GetData(), _T("true")) == 0);
  1014. }
  1015. else if( sItem == _T("ytiled") ) {
  1016. drawInfo.bTiledY = (_tcscmp(sValue.GetData(), _T("true")) == 0);
  1017. }
  1018. else if( sItem == _T("hsl") ) {
  1019. bUseHSL = (_tcscmp(sValue.GetData(), _T("true")) == 0);
  1020. }
  1021. }
  1022. if( *pstrImage++ != _T(' ') ) break;
  1023. }
  1024. drawInfo.sImageName = sImageName;
  1025. const TImageInfo* data = NULL;
  1026. if( bUseRes == false ) {
  1027. data = pManager->GetImageEx((LPCTSTR)sImageName, NULL, dwMask, bUseHSL);
  1028. }
  1029. else {
  1030. data = pManager->GetImageEx((LPCTSTR)sImageName, (LPCTSTR)sImageResType, dwMask, bUseHSL);
  1031. }
  1032. if( !data ) return false;
  1033. drawInfo.pImageInfo = data;
  1034. if( drawInfo.rcBmpPart.left == 0 && drawInfo.rcBmpPart.right == 0 &&
  1035. drawInfo.rcBmpPart.top == 0 && drawInfo.rcBmpPart.bottom == 0 ) {
  1036. drawInfo.rcBmpPart.right = data->nX;
  1037. drawInfo.rcBmpPart.bottom = data->nY;
  1038. }
  1039. }
  1040. if( drawInfo.rcBmpPart.right > drawInfo.pImageInfo->nX ) drawInfo.rcBmpPart.right = drawInfo.pImageInfo->nX;
  1041. if( drawInfo.rcBmpPart.bottom > drawInfo.pImageInfo->nY ) drawInfo.rcBmpPart.bottom = drawInfo.pImageInfo->nY;
  1042. if( hDC == NULL ) return true;
  1043. RECT rcDest = rcItem;
  1044. if( drawInfo.rcDestOffset.left != 0 || drawInfo.rcDestOffset.top != 0 ||
  1045. drawInfo.rcDestOffset.right != 0 || drawInfo.rcDestOffset.bottom != 0 ) {
  1046. rcDest.left = rcItem.left + drawInfo.rcDestOffset.left;
  1047. rcDest.top = rcItem.top + drawInfo.rcDestOffset.top;
  1048. rcDest.right = rcItem.left + drawInfo.rcDestOffset.right;
  1049. if( rcDest.right > rcItem.right ) rcDest.right = rcItem.right;
  1050. rcDest.bottom = rcItem.top + drawInfo.rcDestOffset.bottom;
  1051. if( rcDest.bottom > rcItem.bottom ) rcDest.bottom = rcItem.bottom;
  1052. }
  1053. RECT rcTemp;
  1054. if( !::IntersectRect(&rcTemp, &rcDest, &rcItem) ) return true;
  1055. if( !::IntersectRect(&rcTemp, &rcDest, &rcPaint) ) return true;
  1056. DrawImage(hDC, drawInfo.pImageInfo->hBitmap, rcDest, rcPaint, drawInfo.rcBmpPart, drawInfo.rcScale9,
  1057. drawInfo.pImageInfo->bAlpha, drawInfo.uFade, drawInfo.bHole, drawInfo.bTiledX, drawInfo.bTiledY);
  1058. return true;
  1059. }
  1060. void CRenderEngine::DrawColor(HDC hDC, const RECT& rc, DWORD color)
  1061. {
  1062. if( color <= 0x00FFFFFF ) return;
  1063. if( color >= 0xFF000000 )
  1064. {
  1065. ::SetBkColor(hDC, RGB(GetBValue(color), GetGValue(color), GetRValue(color)));
  1066. ::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
  1067. }
  1068. else
  1069. {
  1070. // Create a new 32bpp bitmap with room for an alpha channel
  1071. BITMAPINFO bmi = { 0 };
  1072. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  1073. bmi.bmiHeader.biWidth = 1;
  1074. bmi.bmiHeader.biHeight = 1;
  1075. bmi.bmiHeader.biPlanes = 1;
  1076. bmi.bmiHeader.biBitCount = 32;
  1077. bmi.bmiHeader.biCompression = BI_RGB;
  1078. bmi.bmiHeader.biSizeImage = 1 * 1 * sizeof(DWORD);
  1079. LPDWORD pDest = NULL;
  1080. HBITMAP hBitmap = ::CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (LPVOID*) &pDest, NULL, 0);
  1081. if( !hBitmap ) return;
  1082. *pDest = color;
  1083. RECT rcBmpPart = {0, 0, 1, 1};
  1084. RECT rcCorners = {0};
  1085. DrawImage(hDC, hBitmap, rc, rc, rcBmpPart, rcCorners, true, 255);
  1086. ::DeleteObject(hBitmap);
  1087. }
  1088. }
  1089. void CRenderEngine::DrawGradient(HDC hDC, const RECT& rc, DWORD dwFirst, DWORD dwSecond, bool bVertical, int nSteps)
  1090. {
  1091. typedef BOOL (WINAPI *LPALPHABLEND)(HDC, int, int, int, int,HDC, int, int, int, int, BLENDFUNCTION);
  1092. static LPALPHABLEND lpAlphaBlend = (LPALPHABLEND) ::GetProcAddress(::GetModuleHandle(_T("msimg32.dll")), "AlphaBlend");
  1093. if( lpAlphaBlend == NULL ) lpAlphaBlend = AlphaBitBlt;
  1094. typedef BOOL (WINAPI *PGradientFill)(HDC, PTRIVERTEX, ULONG, PVOID, ULONG, ULONG);
  1095. static PGradientFill lpGradientFill = (PGradientFill) ::GetProcAddress(::GetModuleHandle(_T("msimg32.dll")), "GradientFill");
  1096. BYTE bAlpha = (BYTE)(((dwFirst >> 24) + (dwSecond >> 24)) >> 1);
  1097. if( bAlpha == 0 ) return;
  1098. int cx = rc.right - rc.left;
  1099. int cy = rc.bottom - rc.top;
  1100. RECT rcPaint = rc;
  1101. HDC hPaintDC = hDC;
  1102. HBITMAP hPaintBitmap = NULL;
  1103. HBITMAP hOldPaintBitmap = NULL;
  1104. if( bAlpha < 255 ) {
  1105. rcPaint.left = rcPaint.top = 0;
  1106. rcPaint.right = cx;
  1107. rcPaint.bottom = cy;
  1108. hPaintDC = ::CreateCompatibleDC(hDC);
  1109. hPaintBitmap = ::CreateCompatibleBitmap(hDC, cx, cy);
  1110. ASSERT(hPaintDC);
  1111. ASSERT(hPaintBitmap);
  1112. hOldPaintBitmap = (HBITMAP) ::SelectObject(hPaintDC, hPaintBitmap);
  1113. }
  1114. if( lpGradientFill != NULL )
  1115. {
  1116. TRIVERTEX triv[2] =
  1117. {
  1118. { rcPaint.left, rcPaint.top, GetBValue(dwFirst) << 8, GetGValue(dwFirst) << 8, GetRValue(dwFirst) << 8, 0xFF00 },
  1119. { rcPaint.right, rcPaint.bottom, GetBValue(dwSecond) << 8, GetGValue(dwSecond) << 8, GetRValue(dwSecond) << 8, 0xFF00 }
  1120. };
  1121. GRADIENT_RECT grc = { 0, 1 };
  1122. lpGradientFill(hPaintDC, triv, 2, &grc, 1, bVertical ? GRADIENT_FILL_RECT_V : GRADIENT_FILL_RECT_H);
  1123. }
  1124. else
  1125. {
  1126. // Determine how many shades
  1127. int nShift = 1;
  1128. if( nSteps >= 64 ) nShift = 6;
  1129. else if( nSteps >= 32 ) nShift = 5;
  1130. else if( nSteps >= 16 ) nShift = 4;
  1131. else if( nSteps >= 8 ) nShift = 3;
  1132. else if( nSteps >= 4 ) nShift = 2;
  1133. int nLines = 1 << nShift;
  1134. for( int i = 0; i < nLines; i++ ) {
  1135. // Do a little alpha blending
  1136. BYTE bR = (BYTE) ((GetBValue(dwSecond) * (nLines - i) + GetBValue(dwFirst) * i) >> nShift);
  1137. BYTE bG = (BYTE) ((GetGValue(dwSecond) * (nLines - i) + GetGValue(dwFirst) * i) >> nShift);
  1138. BYTE bB = (BYTE) ((GetRValue(dwSecond) * (nLines - i) + GetRValue(dwFirst) * i) >> nShift);
  1139. // ... then paint with the resulting color
  1140. HBRUSH hBrush = ::CreateSolidBrush(RGB(bR,bG,bB));
  1141. RECT r2 = rcPaint;
  1142. if( bVertical ) {
  1143. r2.bottom = rc.bottom - ((i * (rc.bottom - rc.top)) >> nShift);
  1144. r2.top = rc.bottom - (((i + 1) * (rc.bottom - rc.top)) >> nShift);
  1145. if( (r2.bottom - r2.top) > 0 ) ::FillRect(hDC, &r2, hBrush);
  1146. }
  1147. else {
  1148. r2.left = rc.right - (((i + 1) * (rc.right - rc.left)) >> nShift);
  1149. r2.right = rc.right - ((i * (rc.right - rc.left)) >> nShift);
  1150. if( (r2.right - r2.left) > 0 ) ::FillRect(hPaintDC, &r2, hBrush);
  1151. }
  1152. ::DeleteObject(hBrush);
  1153. }
  1154. }
  1155. if( bAlpha < 255 ) {
  1156. BLENDFUNCTION bf = { AC_SRC_OVER, 0, bAlpha, AC_SRC_ALPHA };
  1157. lpAlphaBlend(hDC, rc.left, rc.top, cx, cy, hPaintDC, 0, 0, cx, cy, bf);
  1158. ::SelectObject(hPaintDC, hOldPaintBitmap);
  1159. ::DeleteObject(hPaintBitmap);
  1160. ::DeleteDC(hPaintDC);
  1161. }
  1162. }
  1163. void CRenderEngine::DrawLine( HDC hDC, const RECT& rc, int nSize, DWORD dwPenColor, int nStyle)
  1164. {
  1165. ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
  1166. LOGPEN lg;
  1167. lg.lopnColor = RGB(GetBValue(dwPenColor), GetGValue(dwPenColor), GetRValue(dwPenColor));
  1168. lg.lopnStyle = nStyle;
  1169. lg.lopnWidth.x = nSize;
  1170. HPEN hPen = CreatePenIndirect(&lg);
  1171. HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen);
  1172. POINT ptTemp = { 0 };
  1173. ::MoveToEx(hDC, rc.left, rc.top, &ptTemp);
  1174. ::LineTo(hDC, rc.right, rc.bottom);
  1175. ::SelectObject(hDC, hOldPen);
  1176. ::DeleteObject(hPen);
  1177. }
  1178. void CRenderEngine::DrawRect(HDC hDC, const RECT& rc, int nSize, DWORD dwPenColor, int nStyle)
  1179. {
  1180. ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
  1181. HPEN hPen = ::CreatePen(nStyle | PS_INSIDEFRAME, nSize, RGB(GetBValue(dwPenColor), GetGValue(dwPenColor), GetRValue(dwPenColor)));
  1182. HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen);
  1183. ::SelectObject(hDC, ::GetStockObject(HOLLOW_BRUSH));
  1184. ::Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
  1185. ::SelectObject(hDC, hOldPen);
  1186. ::DeleteObject(hPen);
  1187. }
  1188. void CRenderEngine::DrawRoundRect(HDC hDC, const RECT& rc, int nSize, int width, int height, DWORD dwPenColor, int nStyle)
  1189. {
  1190. ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
  1191. HPEN hPen = ::CreatePen(nStyle | PS_INSIDEFRAME, nSize, RGB(GetBValue(dwPenColor), GetGValue(dwPenColor), GetRValue(dwPenColor)));
  1192. HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen);
  1193. ::SelectObject(hDC, ::GetStockObject(HOLLOW_BRUSH));
  1194. ::RoundRect(hDC, rc.left, rc.top, rc.right, rc.bottom, width, height);
  1195. ::SelectObject(hDC, hOldPen);
  1196. ::DeleteObject(hPen);
  1197. }
  1198. void CRenderEngine::DrawText(HDC hDC, CPaintManagerUI* pManager, RECT& rc, LPCTSTR pstrText, DWORD dwTextColor, int iFont, UINT uStyle)
  1199. {
  1200. ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
  1201. if( pstrText == NULL || pManager == NULL ) return;
  1202. CDuiString sText = pstrText;
  1203. CPaintManagerUI::ProcessMultiLanguageTokens(sText);
  1204. pstrText = sText;
  1205. ::SetBkMode(hDC, TRANSPARENT);
  1206. ::SetTextColor(hDC, RGB(GetBValue(dwTextColor), GetGValue(dwTextColor), GetRValue(dwTextColor)));
  1207. HFONT hOldFont = (HFONT)::SelectObject(hDC, pManager->GetFont(iFont));
  1208. ::DrawText(hDC, pstrText, -1, &rc, uStyle | DT_NOPREFIX);
  1209. ::SelectObject(hDC, hOldFont);
  1210. }
  1211. void CRenderEngine::DrawHtmlText(HDC hDC, CPaintManagerUI* pManager, RECT& rc, LPCTSTR pstrText, DWORD dwTextColor, RECT* prcLinks, CDuiString* sLinks, int& nLinkRects, int iDefaultFont, UINT uStyle)
  1212. {
  1213. // 考虑到在xml编辑器中使用<>符号不方便,可以使用{}符号代替
  1214. // 支持标签嵌套(如<l><b>text</b></l>),但是交叉嵌套是应该避免的(如<l><b>text</l></b>)
  1215. // The string formatter supports a kind of "mini-html" that consists of various short tags:
  1216. //
  1217. // Bold: <b>text</b>
  1218. // Color: <c #xxxxxx>text</c> where x = RGB in hex
  1219. // Font: <f x>text</f> where x = font id
  1220. // Italic: <i>text</i>
  1221. // Image: <i x y z> where x = image name and y = imagelist num and z(optional) = imagelist id
  1222. // Link: <a x>text</a> where x(optional) = link content, normal like app:notepad or http:www.xxx.com
  1223. // NewLine <n>
  1224. // Paragraph: <p x>text</p> where x = extra pixels indent in p
  1225. // Raw Text: <r>text</r>
  1226. // Selected: <s>text</s>
  1227. // Underline: <u>text</u>
  1228. // X Indent: <x i> where i = hor indent in pixels
  1229. // Y Indent: <y i> where i = ver indent in pixels
  1230. // Vertical align <v x> where x = top or x = center or x = bottom
  1231. ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
  1232. if( pstrText == NULL || pManager == NULL ) return;
  1233. if( ::IsRectEmpty(&rc) ) return;
  1234. bool bDraw = (uStyle & DT_CALCRECT) == 0;
  1235. CDuiPtrArray aFontArray(10);
  1236. CDuiPtrArray aColorArray(10);
  1237. CDuiPtrArray aPIndentArray(10);
  1238. CDuiPtrArray aVAlignArray(10);
  1239. RECT rcClip = { 0 };
  1240. ::GetClipBox(hDC, &rcClip);
  1241. HRGN hOldRgn = ::CreateRectRgnIndirect(&rcClip);
  1242. HRGN hRgn = ::CreateRectRgnIndirect(&rc);
  1243. if( bDraw ) ::ExtSelectClipRgn(hDC, hRgn, RGN_AND);
  1244. CDuiString sText = pstrText;
  1245. CPaintManagerUI::ProcessMultiLanguageTokens(sText);
  1246. pstrText = sText;
  1247. TEXTMETRIC* pTm = &pManager->GetFontInfo(iDefaultFont)->tm;
  1248. HFONT hOldFont = (HFONT) ::SelectObject(hDC, pManager->GetFontInfo(iDefaultFont)->hFont);
  1249. ::SetBkMode(hDC, TRANSPARENT);
  1250. ::SetTextColor(hDC, RGB(GetBValue(dwTextColor), GetGValue(dwTextColor), GetRValue(dwTextColor)));
  1251. DWORD dwBkColor = pManager->GetDefaultSelectedBkColor();
  1252. ::SetBkColor(hDC, RGB(GetBValue(dwBkColor), GetGValue(dwBkColor), GetRValue(dwBkColor)));
  1253. // If the drawstyle include a alignment, we'll need to first determine the text-size so
  1254. // we can draw it at the correct position...
  1255. if( ((uStyle & DT_CENTER) != 0 || (uStyle & DT_RIGHT) != 0 || (uStyle & DT_VCENTER) != 0 || (uStyle & DT_BOTTOM) != 0) && (uStyle & DT_CALCRECT) == 0 ) {
  1256. RECT rcText = { 0, 0, 9999, 100 };
  1257. if ((uStyle & DT_SINGLELINE) == 0) {
  1258. rcText.right = rc.right - rc.left;
  1259. rcText.bottom = rc.bottom - rc.top;
  1260. }
  1261. int nLinks = 0;
  1262. DrawHtmlText(hDC, pManager, rcText, pstrText, dwTextColor, NULL, NULL, nLinks, iDefaultFont, uStyle | DT_CALCRECT & ~DT_CENTER & ~DT_RIGHT & ~DT_VCENTER & ~DT_BOTTOM);
  1263. if( (uStyle & DT_SINGLELINE) != 0 ){
  1264. if( (uStyle & DT_CENTER) != 0 ) {
  1265. rc.left = rc.left + ((rc.right - rc.left) / 2) - ((rcText.right - rcText.left) / 2);
  1266. rc.right = rc.left + (rcText.right - rcText.left);
  1267. }
  1268. if( (uStyle & DT_RIGHT) != 0 ) {
  1269. rc.left = rc.right - (rcText.right - rcText.left);
  1270. }
  1271. }
  1272. if( (uStyle & DT_VCENTER) != 0 ) {
  1273. rc.top = rc.top + ((rc.bottom - rc.top) / 2) - ((rcText.bottom - rcText.top) / 2);
  1274. rc.bottom = rc.top + (rcText.bottom - rcText.top);
  1275. }
  1276. if( (uStyle & DT_BOTTOM) != 0 ) {
  1277. rc.top = rc.bottom - (rcText.bottom - rcText.top);
  1278. }
  1279. }
  1280. bool bHoverLink = false;
  1281. CDuiString sHoverLink;
  1282. POINT ptMouse = pManager->GetMousePos();
  1283. for( int i = 0; !bHoverLink && i < nLinkRects; i++ ) {
  1284. if( ::PtInRect(prcLinks + i, ptMouse) ) {
  1285. sHoverLink = *(CDuiString*)(sLinks + i);
  1286. bHoverLink = true;
  1287. }
  1288. }
  1289. POINT pt = { rc.left, rc.top };
  1290. int iLinkIndex = 0;
  1291. int cxLine = 0;
  1292. int cyLine = pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1);
  1293. int cyMinHeight = 0;
  1294. int cxMaxWidth = 0;
  1295. POINT ptLinkStart = { 0 };
  1296. bool bLineEnd = false;
  1297. bool bInRaw = false;
  1298. bool bInLink = false;
  1299. bool bInSelected = false;
  1300. int iLineLinkIndex = 0;
  1301. // 排版习惯是图文底部对齐,所以每行绘制都要分两步,先计算高度,再绘制
  1302. CDuiPtrArray aLineFontArray;
  1303. CDuiPtrArray aLineColorArray;
  1304. CDuiPtrArray aLinePIndentArray;
  1305. CDuiPtrArray aLineVAlignArray;
  1306. LPCTSTR pstrLineBegin = pstrText;
  1307. bool bLineInRaw = false;
  1308. bool bLineInLink = false;
  1309. bool bLineInSelected = false;
  1310. UINT iVAlign = DT_BOTTOM;
  1311. int cxLineWidth = 0;
  1312. int cyLineHeight = 0;
  1313. int cxOffset = 0;
  1314. bool bLineDraw = false; // 行的第二阶段:绘制
  1315. while( *pstrText != _T('\0') ) {
  1316. if( pt.x >= rc.right || *pstrText == _T('\n') || bLineEnd ) {
  1317. if( *pstrText == _T('\n') ) pstrText++;
  1318. if( bLineEnd ) bLineEnd = false;
  1319. if( !bLineDraw ) {
  1320. if( bInLink && iLinkIndex < nLinkRects ) {
  1321. ::SetRect(&prcLinks[iLinkIndex++], ptLinkStart.x, ptLinkStart.y, MIN(pt.x, rc.right), pt.y + cyLine);
  1322. CDuiString *pStr1 = (CDuiString*)(sLinks + iLinkIndex - 1);
  1323. CDuiString *pStr2 = (CDuiString*)(sLinks + iLinkIndex);
  1324. *pStr2 = *pStr1;
  1325. }
  1326. for( int i = iLineLinkIndex; i < iLinkIndex; i++ ) {
  1327. prcLinks[i].bottom = pt.y + cyLine;
  1328. }
  1329. if( bDraw ) {
  1330. bInLink = bLineInLink;
  1331. iLinkIndex = iLineLinkIndex;
  1332. }
  1333. }
  1334. else {
  1335. if( bInLink && iLinkIndex < nLinkRects ) iLinkIndex++;
  1336. bLineInLink = bInLink;
  1337. iLineLinkIndex = iLinkIndex;
  1338. }
  1339. if( (uStyle & DT_SINGLELINE) != 0 && (!bDraw || bLineDraw) )
  1340. break;
  1341. if( bDraw ) bLineDraw = !bLineDraw; // !
  1342. pt.x = rc.left;
  1343. cxOffset = 0;
  1344. if (bLineDraw) {
  1345. if( (uStyle & DT_SINGLELINE) == 0 && (uStyle & DT_CENTER) != 0 ) {
  1346. cxOffset = (rc.right - rc.left - cxLineWidth)/2;
  1347. }
  1348. else if( (uStyle & DT_SINGLELINE) == 0 && (uStyle & DT_RIGHT) != 0) {
  1349. cxOffset = rc.right - rc.left - cxLineWidth;
  1350. }
  1351. }
  1352. else {
  1353. pt.y += cyLine;
  1354. }
  1355. if( pt.y > rc.bottom && bDraw )
  1356. break;
  1357. ptLinkStart = pt;
  1358. cyLine = pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1);
  1359. if( pt.x >= rc.right )
  1360. break;
  1361. }
  1362. else if( !bInRaw && ( *pstrText == _T('<') || *pstrText == _T('{') )
  1363. && ( pstrText[1] >= _T('a') && pstrText[1] <= _T('z') )
  1364. && ( pstrText[2] == _T(' ') || pstrText[2] == _T('>') || pstrText[2] == _T('}') ) ) {
  1365. pstrText++;
  1366. LPCTSTR pstrNextStart = NULL;
  1367. switch( *pstrText ) {
  1368. case _T('a'): // Link
  1369. {
  1370. pstrText++;
  1371. while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
  1372. if( iLinkIndex < nLinkRects && !bLineDraw ) {
  1373. CDuiString *pStr = (CDuiString*)(sLinks + iLinkIndex);
  1374. pStr->Empty();
  1375. while( *pstrText != _T('\0') && *pstrText != _T('>') && *pstrText != _T('}') ) {
  1376. LPCTSTR pstrTemp = ::CharNext(pstrText);
  1377. while( pstrText < pstrTemp) {
  1378. *pStr += *pstrText++;
  1379. }
  1380. }
  1381. }
  1382. DWORD clrColor = pManager->GetDefaultLinkFontColor();
  1383. if( bHoverLink && iLinkIndex < nLinkRects ) {
  1384. CDuiString *pStr = (CDuiString*)(sLinks + iLinkIndex);
  1385. if( sHoverLink == *pStr ) clrColor = pManager->GetDefaultLinkHoverFontColor();
  1386. }
  1387. //else if( prcLinks == NULL ) {
  1388. // if( ::PtInRect(&rc, ptMouse) )
  1389. // clrColor = pManager->GetDefaultLinkHoverFontColor();
  1390. //}
  1391. aColorArray.Add((LPVOID)clrColor);
  1392. ::SetTextColor(hDC, RGB(GetBValue(clrColor), GetGValue(clrColor), GetRValue(clrColor)));
  1393. TFontInfo* pFontInfo = pManager->GetFontInfo(iDefaultFont);
  1394. if( aFontArray.GetSize() > 0 ) pFontInfo = (TFontInfo*)aFontArray.GetAt(aFontArray.GetSize() - 1);
  1395. if( pFontInfo->bUnderline == false ) {
  1396. HFONT hFont = pManager->GetFont(pFontInfo->sFontName, pFontInfo->iSize, pFontInfo->bBold, true, pFontInfo->bItalic);
  1397. if( hFont == NULL ) {
  1398. hFont = pManager->AddFont(g_iFontID, pFontInfo->sFontName, pFontInfo->iSize, pFontInfo->bBold, true, pFontInfo->bItalic);
  1399. g_iFontID += 1;
  1400. }
  1401. pFontInfo = pManager->GetFontInfo(hFont);
  1402. aFontArray.Add(pFontInfo);
  1403. pTm = &pFontInfo->tm;
  1404. ::SelectObject(hDC, pFontInfo->hFont);
  1405. cyLine = MAX(cyLine, pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1));
  1406. }
  1407. ptLinkStart = pt;
  1408. bInLink = true;
  1409. }
  1410. break;
  1411. case _T('b'): // Bold
  1412. {
  1413. pstrText++;
  1414. TFontInfo* pFontInfo = pManager->GetFontInfo(iDefaultFont);
  1415. if( aFontArray.GetSize() > 0 ) pFontInfo = (TFontInfo*)aFontArray.GetAt(aFontArray.GetSize() - 1);
  1416. if( pFontInfo->bBold == false ) {
  1417. HFONT hFont = pManager->GetFont(pFontInfo->sFontName, pFontInfo->iSize, true, pFontInfo->bUnderline, pFontInfo->bItalic);
  1418. if( hFont == NULL ) {
  1419. hFont = pManager->AddFont(g_iFontID, pFontInfo->sFontName, pFontInfo->iSize, true, pFontInfo->bUnderline, pFontInfo->bItalic);
  1420. g_iFontID += 1;
  1421. }
  1422. pFontInfo = pManager->GetFontInfo(hFont);
  1423. aFontArray.Add(pFontInfo);
  1424. pTm = &pFontInfo->tm;
  1425. ::SelectObject(hDC, pFontInfo->hFont);
  1426. cyLine = MAX(cyLine, pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1));
  1427. }
  1428. }
  1429. break;
  1430. case _T('c'): // Color
  1431. {
  1432. pstrText++;
  1433. while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
  1434. if( *pstrText == _T('#')) pstrText++;
  1435. DWORD clrColor = _tcstol(pstrText, const_cast<LPTSTR*>(&pstrText), 16);
  1436. aColorArray.Add((LPVOID)clrColor);
  1437. ::SetTextColor(hDC, RGB(GetBValue(clrColor), GetGValue(clrColor), GetRValue(clrColor)));
  1438. }
  1439. break;
  1440. case _T('f'): // Font
  1441. {
  1442. pstrText++;
  1443. while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
  1444. LPCTSTR pstrTemp = pstrText;
  1445. int iFont = (int) _tcstol(pstrText, const_cast<LPTSTR*>(&pstrText), 10);
  1446. //if( isdigit(*pstrText) ) { // debug版本会引起异常
  1447. if( pstrTemp != pstrText ) {
  1448. TFontInfo* pFontInfo = pManager->GetFontInfo(iFont);
  1449. aFontArray.Add(pFontInfo);
  1450. pTm = &pFontInfo->tm;
  1451. ::SelectObject(hDC, pFontInfo->hFont);
  1452. }
  1453. else {
  1454. CDuiString sFontName;
  1455. int iFontSize = 10;
  1456. CDuiString sFontAttr;
  1457. bool bBold = false;
  1458. bool bUnderline = false;
  1459. bool bItalic = false;
  1460. while( *pstrText != _T('\0') && *pstrText != _T('>') && *pstrText != _T('}') && *pstrText != _T(' ') ) {
  1461. pstrTemp = ::CharNext(pstrText);
  1462. while( pstrText < pstrTemp) {
  1463. sFontName += *pstrText++;
  1464. }
  1465. }
  1466. while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
  1467. if( isdigit(*pstrText) ) {
  1468. iFontSize = (int) _tcstol(pstrText, const_cast<LPTSTR*>(&pstrText), 10);
  1469. }
  1470. while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
  1471. while( *pstrText != _T('\0') && *pstrText != _T('>') && *pstrText != _T('}') ) {
  1472. pstrTemp = ::CharNext(pstrText);
  1473. while( pstrText < pstrTemp) {
  1474. sFontAttr += *pstrText++;
  1475. }
  1476. }
  1477. sFontAttr.MakeLower();
  1478. if( sFontAttr.Find(_T("bold")) >= 0 ) bBold = true;
  1479. if( sFontAttr.Find(_T("underline")) >= 0 ) bUnderline = true;
  1480. if( sFontAttr.Find(_T("italic")) >= 0 ) bItalic = true;
  1481. HFONT hFont = pManager->GetFont(sFontName, iFontSize, bBold, bUnderline, bItalic);
  1482. if( hFont == NULL ) {
  1483. hFont = pManager->AddFont(g_iFontID, sFontName, iFontSize, bBold, bUnderline, bItalic);
  1484. g_iFontID += 1;
  1485. }
  1486. TFontInfo* pFontInfo = pManager->GetFontInfo(hFont);
  1487. aFontArray.Add(pFontInfo);
  1488. pTm = &pFontInfo->tm;
  1489. ::SelectObject(hDC, pFontInfo->hFont);
  1490. }
  1491. cyLine = MAX(cyLine, pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1));
  1492. }
  1493. break;
  1494. case _T('i'): // Italic or Image
  1495. {
  1496. pstrNextStart = pstrText - 1;
  1497. pstrText++;
  1498. CDuiString sImageString = pstrText;
  1499. int iWidth = 0;
  1500. int iHeight = 0;
  1501. while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
  1502. const TImageInfo* pImageInfo = NULL;
  1503. CDuiString sName;
  1504. while( *pstrText != _T('\0') && *pstrText != _T('>') && *pstrText != _T('}') && *pstrText != _T(' ') ) {
  1505. LPCTSTR pstrTemp = ::CharNext(pstrText);
  1506. while( pstrText < pstrTemp) {
  1507. sName += *pstrText++;
  1508. }
  1509. }
  1510. if( sName.IsEmpty() ) { // Italic
  1511. pstrNextStart = NULL;
  1512. TFontInfo* pFontInfo = pManager->GetFontInfo(iDefaultFont);
  1513. if( aFontArray.GetSize() > 0 ) pFontInfo = (TFontInfo*)aFontArray.GetAt(aFontArray.GetSize() - 1);
  1514. if( pFontInfo->bItalic == false ) {
  1515. HFONT hFont = pManager->GetFont(pFontInfo->sFontName, pFontInfo->iSize, pFontInfo->bBold, pFontInfo->bUnderline, true);
  1516. if( hFont == NULL ) {
  1517. hFont = pManager->AddFont(g_iFontID, pFontInfo->sFontName, pFontInfo->iSize, pFontInfo->bBold, pFontInfo->bUnderline, true);
  1518. g_iFontID += 1;
  1519. }
  1520. pFontInfo = pManager->GetFontInfo(hFont);
  1521. aFontArray.Add(pFontInfo);
  1522. pTm = &pFontInfo->tm;
  1523. ::SelectObject(hDC, pFontInfo->hFont);
  1524. cyLine = MAX(cyLine, pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1));
  1525. }
  1526. }
  1527. else {
  1528. while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
  1529. int iImageListNum = (int) _tcstol(pstrText, const_cast<LPTSTR*>(&pstrText), 10);
  1530. if( iImageListNum <= 0 ) iImageListNum = 1;
  1531. while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
  1532. int iImageListIndex = (int) _tcstol(pstrText, const_cast<LPTSTR*>(&pstrText), 10);
  1533. if( iImageListIndex < 0 || iImageListIndex >= iImageListNum ) iImageListIndex = 0;
  1534. if( _tcsstr(sImageString.GetData(), _T("file=\'")) != NULL || _tcsstr(sImageString.GetData(), _T("res=\'")) != NULL ) {
  1535. CDuiString sImageResType;
  1536. CDuiString sImageName;
  1537. LPCTSTR pStrImage = sImageString.GetData();
  1538. CDuiString sItem;
  1539. CDuiString sValue;
  1540. while( *pStrImage != _T('\0') ) {
  1541. sItem.Empty();
  1542. sValue.Empty();
  1543. while( *pStrImage > _T('\0') && *pStrImage <= _T(' ') ) pStrImage = ::CharNext(pStrImage);
  1544. while( *pStrImage != _T('\0') && *pStrImage != _T('=') && *pStrImage > _T(' ') ) {
  1545. LPTSTR pstrTemp = ::CharNext(pStrImage);
  1546. while( pStrImage < pstrTemp) {
  1547. sItem += *pStrImage++;
  1548. }
  1549. }
  1550. while( *pStrImage > _T('\0') && *pStrImage <= _T(' ') ) pStrImage = ::CharNext(pStrImage);
  1551. if( *pStrImage++ != _T('=') ) break;
  1552. while( *pStrImage > _T('\0') && *pStrImage <= _T(' ') ) pStrImage = ::CharNext(pStrImage);
  1553. if( *pStrImage++ != _T('\'') ) break;
  1554. while( *pStrImage != _T('\0') && *pStrImage != _T('\'') ) {
  1555. LPTSTR pstrTemp = ::CharNext(pStrImage);
  1556. while( pStrImage < pstrTemp) {
  1557. sValue += *pStrImage++;
  1558. }
  1559. }
  1560. if( *pStrImage++ != _T('\'') ) break;
  1561. if( !sValue.IsEmpty() ) {
  1562. if( sItem == _T("file") || sItem == _T("res") ) {
  1563. sImageName = sValue;
  1564. }
  1565. else if( sItem == _T("restype") ) {
  1566. sImageResType = sValue;
  1567. }
  1568. }
  1569. if( *pStrImage++ != _T(' ') ) break;
  1570. }
  1571. pImageInfo = pManager->GetImageEx((LPCTSTR)sImageName, sImageResType);
  1572. }
  1573. else
  1574. pImageInfo = pManager->GetImageEx((LPCTSTR)sName);
  1575. if( pImageInfo ) {
  1576. iWidth = pImageInfo->nX;
  1577. iHeight = pImageInfo->nY;
  1578. if( iImageListNum > 1 ) iWidth /= iImageListNum;
  1579. if( pt.x + iWidth > rc.right && pt.x > rc.left && (uStyle & DT_SINGLELINE) == 0 ) {
  1580. bLineEnd = true;
  1581. cxLine = pt.x - rc.left;
  1582. }
  1583. else {
  1584. pstrNextStart = NULL;
  1585. if( bDraw && bLineDraw ) {
  1586. CDuiRect rcImage(pt.x + cxOffset, pt.y + cyLineHeight - iHeight, pt.x + + cxOffset + iWidth, pt.y + cyLineHeight);
  1587. iVAlign = DT_BOTTOM;
  1588. if (aVAlignArray.GetSize() > 0) iVAlign = (UINT)aVAlignArray.GetAt(aVAlignArray.GetSize() - 1);
  1589. if (iVAlign == DT_VCENTER) {
  1590. if( iHeight < cyLineHeight ) {
  1591. rcImage.bottom -= (cyLineHeight - iHeight) / 2;
  1592. rcImage.top = rcImage.bottom - iHeight;
  1593. }
  1594. }
  1595. else if (iVAlign == DT_TOP) {
  1596. if( iHeight < cyLineHeight ) {
  1597. rcImage.bottom = pt.y + iHeight;
  1598. rcImage.top = pt.y;
  1599. }
  1600. }
  1601. CDuiRect rcBmpPart(0, 0, iWidth, iHeight);
  1602. rcBmpPart.left = iWidth * iImageListIndex;
  1603. rcBmpPart.right = iWidth * (iImageListIndex + 1);
  1604. CDuiRect rcCorner(0, 0, 0, 0);
  1605. DrawImage(hDC, pImageInfo->hBitmap, rcImage, rcImage, rcBmpPart, rcCorner, \
  1606. pImageInfo->bAlpha, 255);
  1607. }
  1608. cyLine = MAX(iHeight, cyLine);
  1609. pt.x += iWidth;
  1610. cxMaxWidth = MAX(cxMaxWidth, pt.x);
  1611. cxLine = pt.x - rc.left;
  1612. cyMinHeight = pt.y + iHeight;
  1613. }
  1614. }
  1615. else pstrNextStart = NULL;
  1616. }
  1617. }
  1618. break;
  1619. case _T('n'): // Newline
  1620. {
  1621. pstrText++;
  1622. if( (uStyle & DT_SINGLELINE) != 0 ) break;
  1623. bLineEnd = true;
  1624. }
  1625. break;
  1626. case _T('p'): // Paragraph
  1627. {
  1628. pstrText++;
  1629. if( pt.x > rc.left ) bLineEnd = true;
  1630. while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
  1631. int cyLineExtra = (int)_tcstol(pstrText, const_cast<LPTSTR*>(&pstrText), 10);
  1632. aPIndentArray.Add((LPVOID)cyLineExtra);
  1633. cyLine = MAX(cyLine, pTm->tmHeight + pTm->tmExternalLeading + cyLineExtra);
  1634. }
  1635. break;
  1636. case _T('v'): // Vertical Align
  1637. {
  1638. pstrText++;
  1639. while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
  1640. CDuiString sVAlignStyle;
  1641. while( *pstrText != _T('\0') && *pstrText != _T('>') && *pstrText != _T('}') ) {
  1642. LPCTSTR pstrTemp = ::CharNext(pstrText);
  1643. while( pstrText < pstrTemp) {
  1644. sVAlignStyle += *pstrText++;
  1645. }
  1646. }
  1647. UINT iVAlign = DT_BOTTOM;
  1648. if (sVAlignStyle.CompareNoCase(_T("center")) == 0) iVAlign = DT_VCENTER;
  1649. else if (sVAlignStyle.CompareNoCase(_T("top")) == 0) iVAlign = DT_TOP;
  1650. aVAlignArray.Add((LPVOID)iVAlign);
  1651. }
  1652. break;
  1653. case _T('r'): // Raw Text
  1654. {
  1655. pstrText++;
  1656. bInRaw = true;
  1657. }
  1658. break;
  1659. case _T('s'): // Selected text background color
  1660. {
  1661. pstrText++;
  1662. bInSelected = !bInSelected;
  1663. if( bDraw && bLineDraw ) {
  1664. if( bInSelected ) ::SetBkMode(hDC, OPAQUE);
  1665. else ::SetBkMode(hDC, TRANSPARENT);
  1666. }
  1667. }
  1668. break;
  1669. case _T('u'): // Underline text
  1670. {
  1671. pstrText++;
  1672. TFontInfo* pFontInfo = pManager->GetFontInfo(iDefaultFont);
  1673. if( aFontArray.GetSize() > 0 ) pFontInfo = (TFontInfo*)aFontArray.GetAt(aFontArray.GetSize() - 1);
  1674. if( pFontInfo->bUnderline == false ) {
  1675. HFONT hFont = pManager->GetFont(pFontInfo->sFontName, pFontInfo->iSize, pFontInfo->bBold, true, pFontInfo->bItalic);
  1676. if( hFont == NULL ) {
  1677. hFont = pManager->AddFont(g_iFontID, pFontInfo->sFontName, pFontInfo->iSize, pFontInfo->bBold, true, pFontInfo->bItalic);
  1678. g_iFontID += 1;
  1679. }
  1680. pFontInfo = pManager->GetFontInfo(hFont);
  1681. aFontArray.Add(pFontInfo);
  1682. pTm = &pFontInfo->tm;
  1683. ::SelectObject(hDC, pFontInfo->hFont);
  1684. cyLine = MAX(cyLine, pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1));
  1685. }
  1686. }
  1687. break;
  1688. case _T('x'): // X Indent
  1689. {
  1690. pstrText++;
  1691. while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
  1692. int iWidth = (int) _tcstol(pstrText, const_cast<LPTSTR*>(&pstrText), 10);
  1693. pt.x += iWidth;
  1694. }
  1695. break;
  1696. case _T('y'): // Y Indent
  1697. {
  1698. pstrText++;
  1699. while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
  1700. cyLine = (int) _tcstol(pstrText, const_cast<LPTSTR*>(&pstrText), 10);
  1701. }
  1702. break;
  1703. }
  1704. if( pstrNextStart != NULL ) pstrText = pstrNextStart;
  1705. else {
  1706. while( *pstrText != _T('\0') && *pstrText != _T('>') && *pstrText != _T('}') ) pstrText = ::CharNext(pstrText);
  1707. pstrText = ::CharNext(pstrText);
  1708. }
  1709. }
  1710. else if( !bInRaw && ( *pstrText == _T('<') || *pstrText == _T('{') ) && pstrText[1] == _T('/') )
  1711. {
  1712. pstrText++;
  1713. pstrText++;
  1714. switch( *pstrText )
  1715. {
  1716. case _T('c'):
  1717. {
  1718. pstrText++;
  1719. aColorArray.Remove(aColorArray.GetSize() - 1);
  1720. DWORD clrColor = dwTextColor;
  1721. if( aColorArray.GetSize() > 0 ) clrColor = (int)aColorArray.GetAt(aColorArray.GetSize() - 1);
  1722. ::SetTextColor(hDC, RGB(GetBValue(clrColor), GetGValue(clrColor), GetRValue(clrColor)));
  1723. }
  1724. break;
  1725. case _T('p'):
  1726. pstrText++;
  1727. if( pt.x > rc.left ) bLineEnd = true;
  1728. aPIndentArray.Remove(aPIndentArray.GetSize() - 1);
  1729. cyLine = MAX(cyLine, pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1));
  1730. break;
  1731. case _T('v'):
  1732. pstrText++;
  1733. aVAlignArray.Remove(aVAlignArray.GetSize() - 1);
  1734. break;
  1735. case _T('s'):
  1736. {
  1737. pstrText++;
  1738. bInSelected = !bInSelected;
  1739. if( bDraw && bLineDraw ) {
  1740. if( bInSelected ) ::SetBkMode(hDC, OPAQUE);
  1741. else ::SetBkMode(hDC, TRANSPARENT);
  1742. }
  1743. }
  1744. break;
  1745. case _T('a'):
  1746. {
  1747. if( iLinkIndex < nLinkRects ) {
  1748. if( !bLineDraw ) ::SetRect(&prcLinks[iLinkIndex], ptLinkStart.x, ptLinkStart.y, MIN(pt.x, rc.right), pt.y + pTm->tmHeight + pTm->tmExternalLeading);
  1749. iLinkIndex++;
  1750. }
  1751. aColorArray.Remove(aColorArray.GetSize() - 1);
  1752. DWORD clrColor = dwTextColor;
  1753. if( aColorArray.GetSize() > 0 ) clrColor = (int)aColorArray.GetAt(aColorArray.GetSize() - 1);
  1754. ::SetTextColor(hDC, RGB(GetBValue(clrColor), GetGValue(clrColor), GetRValue(clrColor)));
  1755. bInLink = false;
  1756. }
  1757. case _T('b'):
  1758. case _T('f'):
  1759. case _T('i'):
  1760. case _T('u'):
  1761. {
  1762. pstrText++;
  1763. aFontArray.Remove(aFontArray.GetSize() - 1);
  1764. TFontInfo* pFontInfo = (TFontInfo*)aFontArray.GetAt(aFontArray.GetSize() - 1);
  1765. if( pFontInfo == NULL ) pFontInfo = pManager->GetFontInfo(iDefaultFont);
  1766. if( pTm->tmItalic && pFontInfo->bItalic == false ) {
  1767. ABC abc;
  1768. ::GetCharABCWidths(hDC, _T(' '), _T(' '), &abc);
  1769. pt.x += abc.abcC / 2; // 简单修正一下斜体混排的问题, 正确做法应该是http://support.microsoft.com/kb/244798/en-us
  1770. }
  1771. pTm = &pFontInfo->tm;
  1772. ::SelectObject(hDC, pFontInfo->hFont);
  1773. cyLine = MAX(cyLine, pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1));
  1774. }
  1775. break;
  1776. }
  1777. while( *pstrText != _T('\0') && *pstrText != _T('>') && *pstrText != _T('}') ) pstrText = ::CharNext(pstrText);
  1778. pstrText = ::CharNext(pstrText);
  1779. }
  1780. else if( !bInRaw && *pstrText == _T('<') && pstrText[2] == _T('>') && (pstrText[1] == _T('{') || pstrText[1] == _T('}')) )
  1781. {
  1782. SIZE szSpace = { 0 };
  1783. ::GetTextExtentPoint32(hDC, &pstrText[1], 1, &szSpace);
  1784. if( bDraw && bLineDraw ) {
  1785. iVAlign = DT_BOTTOM;
  1786. if (aVAlignArray.GetSize() > 0) iVAlign = (UINT)aVAlignArray.GetAt(aVAlignArray.GetSize() - 1);
  1787. if (iVAlign == DT_VCENTER) ::TextOut(hDC, pt.x + cxOffset, pt.y + (cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading)/2, &pstrText[1], 1);
  1788. else if (iVAlign == DT_TOP) ::TextOut(hDC, pt.x + cxOffset, pt.y, &pstrText[1], 1);
  1789. else ::TextOut(hDC, pt.x + cxOffset, pt.y + cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading, &pstrText[1], 1);
  1790. }
  1791. pt.x += szSpace.cx;
  1792. cxMaxWidth = MAX(cxMaxWidth, pt.x);
  1793. cxLine = pt.x - rc.left;
  1794. pstrText++;pstrText++;pstrText++;
  1795. }
  1796. else if( !bInRaw && *pstrText == _T('{') && pstrText[2] == _T('}') && (pstrText[1] == _T('<') || pstrText[1] == _T('>')) )
  1797. {
  1798. SIZE szSpace = { 0 };
  1799. ::GetTextExtentPoint32(hDC, &pstrText[1], 1, &szSpace);
  1800. if( bDraw && bLineDraw ) {
  1801. iVAlign = DT_BOTTOM;
  1802. if (aVAlignArray.GetSize() > 0) iVAlign = (UINT)aVAlignArray.GetAt(aVAlignArray.GetSize() - 1);
  1803. if (iVAlign == DT_VCENTER) ::TextOut(hDC, pt.x + cxOffset, pt.y + (cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading)/2, &pstrText[1], 1);
  1804. else if (iVAlign == DT_TOP) ::TextOut(hDC, pt.x + cxOffset, pt.y, &pstrText[1], 1);
  1805. else ::TextOut(hDC, pt.x + cxOffset, pt.y + cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading, &pstrText[1], 1);
  1806. }
  1807. pt.x += szSpace.cx;
  1808. cxMaxWidth = MAX(cxMaxWidth, pt.x);
  1809. cxLine = pt.x - rc.left;
  1810. pstrText++;pstrText++;pstrText++;
  1811. }
  1812. else if( !bInRaw && *pstrText == _T(' ') )
  1813. {
  1814. SIZE szSpace = { 0 };
  1815. ::GetTextExtentPoint32(hDC, _T(" "), 1, &szSpace);
  1816. // Still need to paint the space because the font might have
  1817. // underline formatting.
  1818. if( bDraw && bLineDraw ) {
  1819. iVAlign = DT_BOTTOM;
  1820. if (aVAlignArray.GetSize() > 0) iVAlign = (UINT)aVAlignArray.GetAt(aVAlignArray.GetSize() - 1);
  1821. if (iVAlign == DT_VCENTER) ::TextOut(hDC, pt.x + cxOffset, pt.y + (cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading)/2, _T(" "), 1);
  1822. else if (iVAlign == DT_TOP) ::TextOut(hDC, pt.x + cxOffset, pt.y, _T(" "), 1);
  1823. else ::TextOut(hDC, pt.x + cxOffset, pt.y + cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading, _T(" "), 1);
  1824. }
  1825. pt.x += szSpace.cx;
  1826. cxMaxWidth = MAX(cxMaxWidth, pt.x);
  1827. cxLine = pt.x - rc.left;
  1828. pstrText++;
  1829. }
  1830. else
  1831. {
  1832. int cchChars = 0;
  1833. int cchSize = 0;
  1834. int cchLastGoodWord = 0;
  1835. int cchLastGoodSize = 0;
  1836. LPCTSTR p = pstrText;
  1837. LPCTSTR pstrNext;
  1838. SIZE szText = { 0 };
  1839. if( !bInRaw && *p == _T('<') || *p == _T('{') ) p++, cchChars++, cchSize++;
  1840. while( *p != _T('\0') && *p != _T('\n') ) {
  1841. // This part makes sure that we're word-wrapping if needed or providing support
  1842. // for DT_END_ELLIPSIS. Unfortunately the GetTextExtentPoint32() call is pretty
  1843. // slow when repeated so often.
  1844. // TODO: Rewrite and use GetTextExtentExPoint() instead!
  1845. if( bInRaw ) {
  1846. if( ( *p == _T('<') || *p == _T('{') ) && p[1] == _T('/')
  1847. && p[2] == _T('r') && ( p[3] == _T('>') || p[3] == _T('}') ) ) {
  1848. p += 4;
  1849. bInRaw = false;
  1850. break;
  1851. }
  1852. }
  1853. else {
  1854. if( *p == _T('<') || *p == _T('{') ) break;
  1855. }
  1856. pstrNext = ::CharNext(p);
  1857. cchChars++;
  1858. cchSize += (int)(pstrNext - p);
  1859. szText.cx = cchChars * pTm->tmMaxCharWidth;
  1860. if( pt.x + szText.cx >= rc.right ) {
  1861. ::GetTextExtentPoint32(hDC, pstrText, cchSize, &szText);
  1862. }
  1863. if( pt.x + szText.cx > rc.right ) {
  1864. if( pt.x + szText.cx > rc.right && cchChars > 1) {
  1865. cchChars--;
  1866. cchSize -= (int)(pstrNext - p);
  1867. }
  1868. if( (uStyle & DT_WORDBREAK) != 0 && cchLastGoodWord > 0 ) {
  1869. cchChars = cchLastGoodWord;
  1870. cchSize = cchLastGoodSize;
  1871. }
  1872. if( (uStyle & DT_END_ELLIPSIS) != 0 && cchChars > 0 ) {
  1873. cchChars -= 1;
  1874. LPCTSTR pstrPrev = ::CharPrev(pstrText, p);
  1875. if( cchChars > 0 ) {
  1876. cchChars -= 1;
  1877. pstrPrev = ::CharPrev(pstrText, pstrPrev);
  1878. cchSize -= (int)(p - pstrPrev);
  1879. }
  1880. else
  1881. cchSize -= (int)(p - pstrPrev);
  1882. pt.x = rc.right;
  1883. }
  1884. bLineEnd = true;
  1885. cxMaxWidth = MAX(cxMaxWidth, pt.x);
  1886. cxLine = pt.x - rc.left;
  1887. break;
  1888. }
  1889. if (!( ( p[0] >= _T('a') && p[0] <= _T('z') ) || ( p[0] >= _T('A') && p[0] <= _T('Z') ) )) {
  1890. cchLastGoodWord = cchChars;
  1891. cchLastGoodSize = cchSize;
  1892. }
  1893. if( *p == _T(' ') ) {
  1894. cchLastGoodWord = cchChars;
  1895. cchLastGoodSize = cchSize;
  1896. }
  1897. p = ::CharNext(p);
  1898. }
  1899. ::GetTextExtentPoint32(hDC, pstrText, cchSize, &szText);
  1900. if( bDraw && bLineDraw ) {
  1901. iVAlign = DT_BOTTOM;
  1902. if (aVAlignArray.GetSize() > 0) iVAlign = (UINT)aVAlignArray.GetAt(aVAlignArray.GetSize() - 1);
  1903. if (iVAlign == DT_VCENTER) ::TextOut(hDC, pt.x + cxOffset, pt.y + (cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading)/2, pstrText, cchSize);
  1904. else if (iVAlign == DT_TOP) ::TextOut(hDC, pt.x + cxOffset, pt.y, pstrText, cchSize);
  1905. else ::TextOut(hDC, pt.x + cxOffset, pt.y + cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading, pstrText, cchSize);
  1906. if( pt.x >= rc.right && (uStyle & DT_END_ELLIPSIS) != 0 ) {
  1907. if (iVAlign == DT_VCENTER) ::TextOut(hDC, pt.x + cxOffset + szText.cx, pt.y + (cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading)/2, _T("..."), 3);
  1908. else if (iVAlign == DT_TOP) ::TextOut(hDC, pt.x + cxOffset + szText.cx, pt.y, _T("..."), 3);
  1909. else ::TextOut(hDC, pt.x + cxOffset + szText.cx, pt.y + cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading, _T("..."), 3);
  1910. }
  1911. }
  1912. pt.x += szText.cx;
  1913. cxMaxWidth = MAX(cxMaxWidth, pt.x);
  1914. cxLine = pt.x - rc.left;
  1915. pstrText += cchSize;
  1916. }
  1917. if( pt.x >= rc.right || *pstrText == _T('\n') || *pstrText == _T('\0') ) bLineEnd = true;
  1918. if( bDraw && bLineEnd ) {
  1919. if( !bLineDraw ) {
  1920. aFontArray.Resize(aLineFontArray.GetSize());
  1921. ::CopyMemory(aFontArray.GetData(), aLineFontArray.GetData(), aLineFontArray.GetSize() * sizeof(LPVOID));
  1922. aColorArray.Resize(aLineColorArray.GetSize());
  1923. ::CopyMemory(aColorArray.GetData(), aLineColorArray.GetData(), aLineColorArray.GetSize() * sizeof(LPVOID));
  1924. aPIndentArray.Resize(aLinePIndentArray.GetSize());
  1925. ::CopyMemory(aPIndentArray.GetData(), aLinePIndentArray.GetData(), aLinePIndentArray.GetSize() * sizeof(LPVOID));
  1926. aVAlignArray.Resize(aLineVAlignArray.GetSize());
  1927. ::CopyMemory(aVAlignArray.GetData(), aLineVAlignArray.GetData(), aLineVAlignArray.GetSize() * sizeof(LPVOID));
  1928. cxLineWidth = cxLine;
  1929. cyLineHeight = cyLine;
  1930. pstrText = pstrLineBegin;
  1931. bInRaw = bLineInRaw;
  1932. bInSelected = bLineInSelected;
  1933. DWORD clrColor = dwTextColor;
  1934. if( aColorArray.GetSize() > 0 ) clrColor = (int)aColorArray.GetAt(aColorArray.GetSize() - 1);
  1935. ::SetTextColor(hDC, RGB(GetBValue(clrColor), GetGValue(clrColor), GetRValue(clrColor)));
  1936. TFontInfo* pFontInfo = (TFontInfo*)aFontArray.GetAt(aFontArray.GetSize() - 1);
  1937. if( pFontInfo == NULL ) pFontInfo = pManager->GetFontInfo(iDefaultFont);
  1938. pTm = &pFontInfo->tm;
  1939. ::SelectObject(hDC, pFontInfo->hFont);
  1940. if( bInSelected ) ::SetBkMode(hDC, OPAQUE);
  1941. }
  1942. else {
  1943. aLineFontArray.Resize(aFontArray.GetSize());
  1944. ::CopyMemory(aLineFontArray.GetData(), aFontArray.GetData(), aFontArray.GetSize() * sizeof(LPVOID));
  1945. aLineColorArray.Resize(aColorArray.GetSize());
  1946. ::CopyMemory(aLineColorArray.GetData(), aColorArray.GetData(), aColorArray.GetSize() * sizeof(LPVOID));
  1947. aLinePIndentArray.Resize(aPIndentArray.GetSize());
  1948. ::CopyMemory(aLinePIndentArray.GetData(), aPIndentArray.GetData(), aPIndentArray.GetSize() * sizeof(LPVOID));
  1949. aLineVAlignArray.Resize(aVAlignArray.GetSize());
  1950. ::CopyMemory(aLineVAlignArray.GetData(), aVAlignArray.GetData(), aVAlignArray.GetSize() * sizeof(LPVOID));
  1951. pstrLineBegin = pstrText;
  1952. bLineInSelected = bInSelected;
  1953. bLineInRaw = bInRaw;
  1954. }
  1955. }
  1956. ASSERT(iLinkIndex<=nLinkRects);
  1957. }
  1958. nLinkRects = iLinkIndex;
  1959. // Return size of text when requested
  1960. if( (uStyle & DT_CALCRECT) != 0 ) {
  1961. rc.bottom = MAX(cyMinHeight, pt.y + cyLine);
  1962. rc.right = MIN(rc.right, cxMaxWidth);
  1963. }
  1964. if( bDraw ) ::SelectClipRgn(hDC, hOldRgn);
  1965. ::DeleteObject(hOldRgn);
  1966. ::DeleteObject(hRgn);
  1967. ::SelectObject(hDC, hOldFont);
  1968. }
  1969. HBITMAP CRenderEngine::GenerateBitmap(CPaintManagerUI* pManager, RECT rc, CControlUI* pStopControl, DWORD dwFilterColor)
  1970. {
  1971. if (pManager == NULL) return NULL;
  1972. int cx = rc.right - rc.left;
  1973. int cy = rc.bottom - rc.top;
  1974. bool bUseOffscreenBitmap = true;
  1975. HDC hPaintDC = ::CreateCompatibleDC(pManager->GetPaintDC());
  1976. ASSERT(hPaintDC);
  1977. HBITMAP hPaintBitmap = NULL;
  1978. if (pStopControl == NULL && !pManager->IsLayered()) hPaintBitmap = pManager->GetPaintOffscreenBitmap();
  1979. if( hPaintBitmap == NULL ) {
  1980. bUseOffscreenBitmap = false;
  1981. hPaintBitmap = ::CreateCompatibleBitmap(pManager->GetPaintDC(), rc.right, rc.bottom);
  1982. ASSERT(hPaintBitmap);
  1983. }
  1984. HBITMAP hOldPaintBitmap = (HBITMAP) ::SelectObject(hPaintDC, hPaintBitmap);
  1985. if (!bUseOffscreenBitmap) {
  1986. CControlUI* pRoot = pManager->GetRoot();
  1987. pRoot->Paint(hPaintDC, rc, pStopControl);
  1988. }
  1989. BITMAPINFO bmi = { 0 };
  1990. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  1991. bmi.bmiHeader.biWidth = cx;
  1992. bmi.bmiHeader.biHeight = cy;
  1993. bmi.bmiHeader.biPlanes = 1;
  1994. bmi.bmiHeader.biBitCount = 32;
  1995. bmi.bmiHeader.biCompression = BI_RGB;
  1996. bmi.bmiHeader.biSizeImage = cx * cy * sizeof(DWORD);
  1997. LPDWORD pDest = NULL;
  1998. HDC hCloneDC = ::CreateCompatibleDC(pManager->GetPaintDC());
  1999. HBITMAP hBitmap = ::CreateDIBSection(pManager->GetPaintDC(), &bmi, DIB_RGB_COLORS, (LPVOID*) &pDest, NULL, 0);
  2000. ASSERT(hCloneDC);
  2001. ASSERT(hBitmap);
  2002. if( hBitmap != NULL )
  2003. {
  2004. HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(hCloneDC, hBitmap);
  2005. ::BitBlt(hCloneDC, 0, 0, cx, cy, hPaintDC, rc.left, rc.top, SRCCOPY);
  2006. RECT rcClone = {0, 0, cx, cy};
  2007. if (dwFilterColor > 0x00FFFFFF) DrawColor(hCloneDC, rcClone, dwFilterColor);
  2008. ::SelectObject(hCloneDC, hOldBitmap);
  2009. ::DeleteDC(hCloneDC);
  2010. ::GdiFlush();
  2011. }
  2012. // Cleanup
  2013. ::SelectObject(hPaintDC, hOldPaintBitmap);
  2014. if (!bUseOffscreenBitmap) ::DeleteObject(hPaintBitmap);
  2015. ::DeleteDC(hPaintDC);
  2016. return hBitmap;
  2017. }
  2018. HBITMAP CRenderEngine::GenerateBitmap(CPaintManagerUI* pManager, CControlUI* pControl, RECT rc, DWORD dwFilterColor)
  2019. {
  2020. if (pManager == NULL || pControl == NULL) return NULL;
  2021. int cx = rc.right - rc.left;
  2022. int cy = rc.bottom - rc.top;
  2023. HDC hPaintDC = ::CreateCompatibleDC(pManager->GetPaintDC());
  2024. HBITMAP hPaintBitmap = ::CreateCompatibleBitmap(pManager->GetPaintDC(), rc.right, rc.bottom);
  2025. ASSERT(hPaintDC);
  2026. ASSERT(hPaintBitmap);
  2027. HBITMAP hOldPaintBitmap = (HBITMAP) ::SelectObject(hPaintDC, hPaintBitmap);
  2028. pControl->Paint(hPaintDC, rc, NULL);
  2029. BITMAPINFO bmi = { 0 };
  2030. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  2031. bmi.bmiHeader.biWidth = cx;
  2032. bmi.bmiHeader.biHeight = cy;
  2033. bmi.bmiHeader.biPlanes = 1;
  2034. bmi.bmiHeader.biBitCount = 32;
  2035. bmi.bmiHeader.biCompression = BI_RGB;
  2036. bmi.bmiHeader.biSizeImage = cx * cy * sizeof(DWORD);
  2037. LPDWORD pDest = NULL;
  2038. HDC hCloneDC = ::CreateCompatibleDC(pManager->GetPaintDC());
  2039. HBITMAP hBitmap = ::CreateDIBSection(pManager->GetPaintDC(), &bmi, DIB_RGB_COLORS, (LPVOID*) &pDest, NULL, 0);
  2040. ASSERT(hCloneDC);
  2041. ASSERT(hBitmap);
  2042. if( hBitmap != NULL )
  2043. {
  2044. HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(hCloneDC, hBitmap);
  2045. ::BitBlt(hCloneDC, 0, 0, cx, cy, hPaintDC, rc.left, rc.top, SRCCOPY);
  2046. RECT rcClone = {0, 0, cx, cy};
  2047. if (dwFilterColor > 0x00FFFFFF) DrawColor(hCloneDC, rcClone, dwFilterColor);
  2048. ::SelectObject(hCloneDC, hOldBitmap);
  2049. ::DeleteDC(hCloneDC);
  2050. ::GdiFlush();
  2051. }
  2052. // Cleanup
  2053. ::SelectObject(hPaintDC, hOldPaintBitmap);
  2054. ::DeleteObject(hPaintBitmap);
  2055. ::DeleteDC(hPaintDC);
  2056. return hBitmap;
  2057. }
  2058. SIZE CRenderEngine::GetTextSize( HDC hDC, CPaintManagerUI* pManager , LPCTSTR pstrText, int iFont, UINT uStyle )
  2059. {
  2060. CDuiString sText = pstrText;
  2061. CPaintManagerUI::ProcessMultiLanguageTokens(sText);
  2062. pstrText = sText;
  2063. SIZE size = {0,0};
  2064. ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
  2065. if( pstrText == NULL || pManager == NULL ) return size;
  2066. ::SetBkMode(hDC, TRANSPARENT);
  2067. HFONT hOldFont = (HFONT)::SelectObject(hDC, pManager->GetFont(iFont));
  2068. GetTextExtentPoint32(hDC, pstrText, _tcslen(pstrText) , &size);
  2069. ::SelectObject(hDC, hOldFont);
  2070. return size;
  2071. }
  2072. } // namespace DuiLib