| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200 |
- #include "StdAfx.h"
- ///////////////////////////////////////////////////////////////////////////////////////
- DECLARE_HANDLE(HZIP); // An HZIP identifies a zip file that has been opened
- typedef DWORD ZRESULT;
- typedef struct
- {
- int index; // index of this file within the zip
- char name[MAX_PATH]; // filename within the zip
- DWORD attr; // attributes, as in GetFileAttributes.
- FILETIME atime,ctime,mtime;// access, create, modify filetimes
- long comp_size; // sizes of item, compressed and uncompressed. These
- long unc_size; // may be -1 if not yet known (e.g. being streamed in)
- } ZIPENTRY;
- typedef struct
- {
- int index; // index of this file within the zip
- TCHAR name[MAX_PATH]; // filename within the zip
- DWORD attr; // attributes, as in GetFileAttributes.
- FILETIME atime,ctime,mtime;// access, create, modify filetimes
- long comp_size; // sizes of item, compressed and uncompressed. These
- long unc_size; // may be -1 if not yet known (e.g. being streamed in)
- } ZIPENTRYW;
- #define OpenZip OpenZipU
- #define CloseZip(hz) CloseZipU(hz)
- extern HZIP OpenZipU(void *z,unsigned int len,DWORD flags);
- extern ZRESULT CloseZipU(HZIP hz);
- #ifdef _UNICODE
- #define ZIPENTRY ZIPENTRYW
- #define GetZipItem GetZipItemW
- #define FindZipItem FindZipItemW
- #else
- #define GetZipItem GetZipItemA
- #define FindZipItem FindZipItemA
- #endif
- extern ZRESULT GetZipItemA(HZIP hz, int index, ZIPENTRY *ze);
- extern ZRESULT GetZipItemW(HZIP hz, int index, ZIPENTRYW *ze);
- extern ZRESULT FindZipItemA(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRY *ze);
- extern ZRESULT FindZipItemW(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRYW *ze);
- extern ZRESULT UnzipItem(HZIP hz, int index, void *dst, unsigned int len, DWORD flags);
- ///////////////////////////////////////////////////////////////////////////////////////
- #define RES_TYPE_COLOR _T("*COLOR*")
- extern "C"
- {
- extern unsigned char *stbi_load_from_memory(unsigned char const *buffer, int len, int *x, int *y, \
- int *comp, int req_comp);
- extern void stbi_image_free(void *retval_from_stbi_load);
- };
- namespace DuiLib {
- static int g_iFontID = MAX_FONT_ID;
- /////////////////////////////////////////////////////////////////////////////////////
- //
- //
- CRenderClip::~CRenderClip()
- {
- ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
- ASSERT(::GetObjectType(hRgn)==OBJ_REGION);
- ASSERT(::GetObjectType(hOldRgn)==OBJ_REGION);
- ::SelectClipRgn(hDC, hOldRgn);
- ::DeleteObject(hOldRgn);
- ::DeleteObject(hRgn);
- }
- void CRenderClip::GenerateClip(HDC hDC, RECT rc, CRenderClip& clip)
- {
- RECT rcClip = { 0 };
- ::GetClipBox(hDC, &rcClip);
- clip.hOldRgn = ::CreateRectRgnIndirect(&rcClip);
- clip.hRgn = ::CreateRectRgnIndirect(&rc);
- ::CombineRgn(clip.hRgn, clip.hRgn, clip.hOldRgn, RGN_AND);
- ::SelectClipRgn(hDC, clip.hRgn);
- clip.hDC = hDC;
- clip.rcItem = rc;
- }
- void CRenderClip::GenerateRoundClip(HDC hDC, RECT rc, RECT rcItem, int width, int height, CRenderClip& clip)
- {
- RECT rcClip = { 0 };
- ::GetClipBox(hDC, &rcClip);
- clip.hOldRgn = ::CreateRectRgnIndirect(&rcClip);
- clip.hRgn = ::CreateRectRgnIndirect(&rc);
- HRGN hRgnItem = ::CreateRoundRectRgn(rcItem.left, rcItem.top, rcItem.right + 1, rcItem.bottom + 1, width, height);
- ::CombineRgn(clip.hRgn, clip.hRgn, hRgnItem, RGN_AND);
- ::CombineRgn(clip.hRgn, clip.hRgn, clip.hOldRgn, RGN_AND);
- ::SelectClipRgn(hDC, clip.hRgn);
- clip.hDC = hDC;
- clip.rcItem = rc;
- ::DeleteObject(hRgnItem);
- }
- void CRenderClip::UseOldClipBegin(HDC hDC, CRenderClip& clip)
- {
- ::SelectClipRgn(hDC, clip.hOldRgn);
- }
- void CRenderClip::UseOldClipEnd(HDC hDC, CRenderClip& clip)
- {
- ::SelectClipRgn(hDC, clip.hRgn);
- }
- /////////////////////////////////////////////////////////////////////////////////////
- //
- //
- static const float OneThird = 1.0f / 3;
- static void RGBtoHSL(DWORD ARGB, float* H, float* S, float* L) {
- const float
- R = (float)GetRValue(ARGB),
- G = (float)GetGValue(ARGB),
- B = (float)GetBValue(ARGB),
- nR = (R<0?0:(R>255?255:R))/255,
- nG = (G<0?0:(G>255?255:G))/255,
- nB = (B<0?0:(B>255?255:B))/255,
- m = min(min(nR,nG),nB),
- M = max(max(nR,nG),nB);
- *L = (m + M)/2;
- if (M==m) *H = *S = 0;
- else {
- const float
- f = (nR==m)?(nG-nB):((nG==m)?(nB-nR):(nR-nG)),
- i = (nR==m)?3.0f:((nG==m)?5.0f:1.0f);
- *H = (i-f/(M-m));
- if (*H>=6) *H-=6;
- *H*=60;
- *S = (2*(*L)<=1)?((M-m)/(M+m)):((M-m)/(2-M-m));
- }
- }
- static void HSLtoRGB(DWORD* ARGB, float H, float S, float L) {
- const float
- q = 2*L<1?L*(1+S):(L+S-L*S),
- p = 2*L-q,
- h = H/360,
- tr = h + OneThird,
- tg = h,
- tb = h - OneThird,
- ntr = tr<0?tr+1:(tr>1?tr-1:tr),
- ntg = tg<0?tg+1:(tg>1?tg-1:tg),
- ntb = tb<0?tb+1:(tb>1?tb-1:tb),
- 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))),
- 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))),
- 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)));
- *ARGB &= 0xFF000000;
- *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)) );
- }
- static COLORREF PixelAlpha(COLORREF clrSrc, double src_darken, COLORREF clrDest, double dest_darken)
- {
- return RGB (GetRValue (clrSrc) * src_darken + GetRValue (clrDest) * dest_darken,
- GetGValue (clrSrc) * src_darken + GetGValue (clrDest) * dest_darken,
- GetBValue (clrSrc) * src_darken + GetBValue (clrDest) * dest_darken);
- }
- static BOOL WINAPI AlphaBitBlt(HDC hDC, int nDestX, int nDestY, int dwWidth, int dwHeight, HDC hSrcDC, \
- int nSrcX, int nSrcY, int wSrc, int hSrc, BLENDFUNCTION ftn)
- {
- HDC hTempDC = ::CreateCompatibleDC(hDC);
- if (NULL == hTempDC)
- return FALSE;
- //Creates Source DIB
- LPBITMAPINFO lpbiSrc = NULL;
- // Fill in the BITMAPINFOHEADER
- lpbiSrc = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)];
- if (lpbiSrc == NULL)
- {
- ::DeleteDC(hTempDC);
- return FALSE;
- }
- lpbiSrc->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- lpbiSrc->bmiHeader.biWidth = dwWidth;
- lpbiSrc->bmiHeader.biHeight = dwHeight;
- lpbiSrc->bmiHeader.biPlanes = 1;
- lpbiSrc->bmiHeader.biBitCount = 32;
- lpbiSrc->bmiHeader.biCompression = BI_RGB;
- lpbiSrc->bmiHeader.biSizeImage = dwWidth * dwHeight;
- lpbiSrc->bmiHeader.biXPelsPerMeter = 0;
- lpbiSrc->bmiHeader.biYPelsPerMeter = 0;
- lpbiSrc->bmiHeader.biClrUsed = 0;
- lpbiSrc->bmiHeader.biClrImportant = 0;
- COLORREF* pSrcBits = NULL;
- HBITMAP hSrcDib = CreateDIBSection (
- hSrcDC, lpbiSrc, DIB_RGB_COLORS, (void **)&pSrcBits,
- NULL, NULL);
- if ((NULL == hSrcDib) || (NULL == pSrcBits))
- {
- delete [] lpbiSrc;
- ::DeleteDC(hTempDC);
- return FALSE;
- }
- HBITMAP hOldTempBmp = (HBITMAP)::SelectObject (hTempDC, hSrcDib);
- ::StretchBlt(hTempDC, 0, 0, dwWidth, dwHeight, hSrcDC, nSrcX, nSrcY, wSrc, hSrc, SRCCOPY);
- ::SelectObject (hTempDC, hOldTempBmp);
- //Creates Destination DIB
- LPBITMAPINFO lpbiDest = NULL;
- // Fill in the BITMAPINFOHEADER
- lpbiDest = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)];
- if (lpbiDest == NULL)
- {
- delete [] lpbiSrc;
- ::DeleteObject(hSrcDib);
- ::DeleteDC(hTempDC);
- return FALSE;
- }
- lpbiDest->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- lpbiDest->bmiHeader.biWidth = dwWidth;
- lpbiDest->bmiHeader.biHeight = dwHeight;
- lpbiDest->bmiHeader.biPlanes = 1;
- lpbiDest->bmiHeader.biBitCount = 32;
- lpbiDest->bmiHeader.biCompression = BI_RGB;
- lpbiDest->bmiHeader.biSizeImage = dwWidth * dwHeight;
- lpbiDest->bmiHeader.biXPelsPerMeter = 0;
- lpbiDest->bmiHeader.biYPelsPerMeter = 0;
- lpbiDest->bmiHeader.biClrUsed = 0;
- lpbiDest->bmiHeader.biClrImportant = 0;
- COLORREF* pDestBits = NULL;
- HBITMAP hDestDib = CreateDIBSection (
- hDC, lpbiDest, DIB_RGB_COLORS, (void **)&pDestBits,
- NULL, NULL);
- if ((NULL == hDestDib) || (NULL == pDestBits))
- {
- delete [] lpbiSrc;
- ::DeleteObject(hSrcDib);
- ::DeleteDC(hTempDC);
- return FALSE;
- }
- ::SelectObject (hTempDC, hDestDib);
- ::BitBlt (hTempDC, 0, 0, dwWidth, dwHeight, hDC, nDestX, nDestY, SRCCOPY);
- ::SelectObject (hTempDC, hOldTempBmp);
- double src_darken;
- BYTE nAlpha;
- for (int pixel = 0; pixel < dwWidth * dwHeight; pixel++, pSrcBits++, pDestBits++)
- {
- nAlpha = LOBYTE(*pSrcBits >> 24);
- src_darken = (double) (nAlpha * ftn.SourceConstantAlpha) / 255.0 / 255.0;
- if( src_darken < 0.0 ) src_darken = 0.0;
- *pDestBits = PixelAlpha(*pSrcBits, src_darken, *pDestBits, 1.0 - src_darken);
- } //for
- ::SelectObject (hTempDC, hDestDib);
- ::BitBlt (hDC, nDestX, nDestY, dwWidth, dwHeight, hTempDC, 0, 0, SRCCOPY);
- ::SelectObject (hTempDC, hOldTempBmp);
- delete [] lpbiDest;
- ::DeleteObject(hDestDib);
- delete [] lpbiSrc;
- ::DeleteObject(hSrcDib);
- ::DeleteDC(hTempDC);
- return TRUE;
- }
- /////////////////////////////////////////////////////////////////////////////////////
- //
- //
- DWORD CRenderEngine::AdjustColor(DWORD dwColor, short H, short S, short L)
- {
- if( H == 180 && S == 100 && L == 100 ) return dwColor;
- float fH, fS, fL;
- float S1 = S / 100.0f;
- float L1 = L / 100.0f;
- RGBtoHSL(dwColor, &fH, &fS, &fL);
- fH += (H - 180);
- fH = fH > 0 ? fH : fH + 360;
- fS *= S1;
- fL *= L1;
- HSLtoRGB(&dwColor, fH, fS, fL);
- return dwColor;
- }
- HBITMAP CRenderEngine::CreateARGB32Bitmap(HDC hDC, int cx, int cy, COLORREF** pBits)
- {
- LPBITMAPINFO lpbiSrc = NULL;
- lpbiSrc = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)];
- if (lpbiSrc == NULL) return NULL;
- lpbiSrc->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- lpbiSrc->bmiHeader.biWidth = cx;
- lpbiSrc->bmiHeader.biHeight = cy;
- lpbiSrc->bmiHeader.biPlanes = 1;
- lpbiSrc->bmiHeader.biBitCount = 32;
- lpbiSrc->bmiHeader.biCompression = BI_RGB;
- lpbiSrc->bmiHeader.biSizeImage = cx * cy;
- lpbiSrc->bmiHeader.biXPelsPerMeter = 0;
- lpbiSrc->bmiHeader.biYPelsPerMeter = 0;
- lpbiSrc->bmiHeader.biClrUsed = 0;
- lpbiSrc->bmiHeader.biClrImportant = 0;
- HBITMAP hBitmap = CreateDIBSection (hDC, lpbiSrc, DIB_RGB_COLORS, (void **)pBits, NULL, NULL);
- delete [] lpbiSrc;
- return hBitmap;
- }
- void CRenderEngine::AdjustImage(bool bUseHSL, TImageInfo* imageInfo, short H, short S, short L)
- {
- if( imageInfo == NULL || imageInfo->bUseHSL == false || imageInfo->hBitmap == NULL ||
- imageInfo->pBits == NULL || imageInfo->pSrcBits == NULL )
- return;
- if( bUseHSL == false || (H == 180 && S == 100 && L == 100)) {
- ::CopyMemory(imageInfo->pBits, imageInfo->pSrcBits, imageInfo->nX * imageInfo->nY * 4);
- return;
- }
- float fH, fS, fL;
- float S1 = S / 100.0f;
- float L1 = L / 100.0f;
- for( int i = 0; i < imageInfo->nX * imageInfo->nY; i++ ) {
- RGBtoHSL(*(DWORD*)(imageInfo->pSrcBits + i*4), &fH, &fS, &fL);
- fH += (H - 180);
- fH = fH > 0 ? fH : fH + 360;
- fS *= S1;
- fL *= L1;
- HSLtoRGB((DWORD*)(imageInfo->pBits + i*4), fH, fS, fL);
- }
- }
- TImageInfo* CRenderEngine::LoadImage(STRINGorID bitmap, LPCTSTR type, DWORD mask)
- {
- LPBYTE pData = NULL;
- DWORD dwSize = 0;
- do
- {
- if( type == NULL ) {
- CDuiString sFile = CPaintManagerUI::GetResourcePath();
- if( CPaintManagerUI::GetResourceZip().IsEmpty() ) {
- sFile += bitmap.m_lpstr;
- HANDLE hFile = ::CreateFile(sFile.GetData(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, \
- FILE_ATTRIBUTE_NORMAL, NULL);
- if( hFile == INVALID_HANDLE_VALUE ) break;
- dwSize = ::GetFileSize(hFile, NULL);
- if (dwSize == 0)
- {
- ::CloseHandle(hFile);
- break;
- }
- DWORD dwRead = 0;
- pData = new BYTE[ dwSize ];
- ::ReadFile( hFile, pData, dwSize, &dwRead, NULL );
- ::CloseHandle( hFile );
- if( dwRead != dwSize ) {
- delete[] pData;
- pData = NULL;
- break;
- }
- }
- else {
- sFile += CPaintManagerUI::GetResourceZip();
- HZIP hz = NULL;
- if( CPaintManagerUI::IsCachedResourceZip() ) hz = (HZIP)CPaintManagerUI::GetResourceZipHandle();
- else hz = OpenZip((void*)sFile.GetData(), 0, 2);
- if( hz == NULL ) break;
- ZIPENTRY ze;
- int i;
- if( FindZipItem(hz, bitmap.m_lpstr, true, &i, &ze) != 0 ) break;
- dwSize = ze.unc_size;
- if( dwSize == 0 ) break;
- pData = new BYTE[ dwSize ];
- int res = UnzipItem(hz, i, pData, dwSize, 3);
- if( res != 0x00000000 && res != 0x00000600) {
- delete[] pData;
- pData = NULL;
- if( !CPaintManagerUI::IsCachedResourceZip() ) CloseZip(hz);
- break;
- }
- if( !CPaintManagerUI::IsCachedResourceZip() ) CloseZip(hz);
- }
- }
- else if (_tcscmp(type, RES_TYPE_COLOR) == 0) {
- pData = (PBYTE)0x1; /* dummy pointer */
- }
- else {
- HRSRC hResource = ::FindResource(CPaintManagerUI::GetResourceDll(), bitmap.m_lpstr, type);
- if( hResource == NULL ) break;
- HGLOBAL hGlobal = ::LoadResource(CPaintManagerUI::GetResourceDll(), hResource);
- if( hGlobal == NULL ) {
- FreeResource(hResource);
- break;
- }
- dwSize = ::SizeofResource(CPaintManagerUI::GetResourceDll(), hResource);
- if( dwSize == 0 ) break;
- pData = new BYTE[ dwSize ];
- ::CopyMemory(pData, (LPBYTE)::LockResource(hGlobal), dwSize);
- ::FreeResource(hResource);
- }
- } while (0);
- while (!pData)
- {
- //读不到图片, 则直接去读取bitmap.m_lpstr指向的路径
- HANDLE hFile = ::CreateFile(bitmap.m_lpstr, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, \
- FILE_ATTRIBUTE_NORMAL, NULL);
- if( hFile == INVALID_HANDLE_VALUE ) break;
- dwSize = ::GetFileSize(hFile, NULL);
- if (dwSize == 0)
- {
- ::CloseHandle(hFile);
- break;
- }
- DWORD dwRead = 0;
- pData = new BYTE[ dwSize ];
- ::ReadFile( hFile, pData, dwSize, &dwRead, NULL );
- ::CloseHandle( hFile );
- if( dwRead != dwSize ) {
- delete[] pData;
- pData = NULL;
- }
- break;
- }
- if (!pData)
- {
- //::MessageBox(0, _T("读取图片数据失败!"), _T("抓BUG"), MB_OK);
- return NULL;
- }
- LPBYTE pImage = NULL;
- int x = 1, y = 1, n;
- if (!type || _tcscmp(type, RES_TYPE_COLOR) != 0) {
- pImage = stbi_load_from_memory(pData, dwSize, &x, &y, &n, 4);
- delete[] pData;
- if( !pImage ) {
- //::MessageBox(0, _T("解析图片失败"), _T("抓BUG"), MB_OK);
- return NULL;
- }
- }
- BITMAPINFO bmi;
- ::ZeroMemory(&bmi, sizeof(BITMAPINFO));
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = x;
- bmi.bmiHeader.biHeight = -y;
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
- bmi.bmiHeader.biSizeImage = x * y * 4;
- bool bAlphaChannel = false;
- LPBYTE pDest = NULL;
- HBITMAP hBitmap = ::CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**)&pDest, NULL, 0);
- if( !hBitmap ) {
- //::MessageBox(0, _T("CreateDIBSection失败"), _T("抓BUG"), MB_OK);
- return NULL;
- }
- BYTE bColorBits[4] = { 0 };
- if (type && _tcscmp(type, RES_TYPE_COLOR) == 0) {
- LPTSTR pstr = NULL;
- LPCTSTR pstrValue = bitmap.m_lpstr;
- if (*pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
- DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
- pImage = (LPBYTE)&clrColor;
- /* BGRA -> RGBA */
- bColorBits[3] = pImage[3];
- bColorBits[2] = pImage[0];
- bColorBits[1] = pImage[1];
- bColorBits[0] = pImage[2];
- pImage = bColorBits;
- }
- for( int i = 0; i < x * y; i++ )
- {
- pDest[i*4 + 3] = pImage[i*4 + 3];
- if( pDest[i*4 + 3] < 255 )
- {
- pDest[i*4] = (BYTE)(DWORD(pImage[i*4 + 2])*pImage[i*4 + 3]/255);
- pDest[i*4 + 1] = (BYTE)(DWORD(pImage[i*4 + 1])*pImage[i*4 + 3]/255);
- pDest[i*4 + 2] = (BYTE)(DWORD(pImage[i*4])*pImage[i*4 + 3]/255);
- bAlphaChannel = true;
- }
- else
- {
- pDest[i*4] = pImage[i*4 + 2];
- pDest[i*4 + 1] = pImage[i*4 + 1];
- pDest[i*4 + 2] = pImage[i*4];
- }
- if( *(DWORD*)(&pDest[i*4]) == mask ) {
- pDest[i*4] = (BYTE)0;
- pDest[i*4 + 1] = (BYTE)0;
- pDest[i*4 + 2] = (BYTE)0;
- pDest[i*4 + 3] = (BYTE)0;
- bAlphaChannel = true;
- }
- }
- if (!type || _tcscmp(type, RES_TYPE_COLOR) != 0) {
- stbi_image_free(pImage);
- }
- TImageInfo* data = new TImageInfo;
- data->hBitmap = hBitmap;
- data->pBits = pDest;
- data->nX = x;
- data->nY = y;
- data->bAlpha = bAlphaChannel;
- data->bUseHSL = false;
- data->pSrcBits = NULL;
- return data;
- }
- void CRenderEngine::FreeImage(TImageInfo* bitmap, bool bDelete)
- {
- if (bitmap == NULL) return;
- if (bitmap->hBitmap) {
- ::DeleteObject(bitmap->hBitmap);
- bitmap->hBitmap = NULL;
- }
- if (bitmap->pSrcBits) {
- delete[] bitmap->pSrcBits;
- bitmap->pSrcBits = NULL;
- }
- if (bDelete) delete bitmap ;
- }
- void CRenderEngine::DrawImage(HDC hDC, HBITMAP hBitmap, const RECT& rc, const RECT& rcPaint,
- const RECT& rcBmpPart, const RECT& rcScale9, bool bAlpha,
- BYTE uFade, bool bHole, bool bTiledX, bool bTiledY)
- {
- ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
- typedef BOOL (WINAPI *LPALPHABLEND)(HDC, int, int, int, int,HDC, int, int, int, int, BLENDFUNCTION);
- static LPALPHABLEND lpAlphaBlend = (LPALPHABLEND) ::GetProcAddress(::GetModuleHandle(_T("msimg32.dll")), "AlphaBlend");
- if( lpAlphaBlend == NULL ) lpAlphaBlend = AlphaBitBlt;
- if( hBitmap == NULL ) return;
- HDC hCloneDC = ::CreateCompatibleDC(hDC);
- HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(hCloneDC, hBitmap);
- ::SetStretchBltMode(hDC, COLORONCOLOR);
- RECT rcTemp = {0};
- RECT rcDest = {0};
- if( lpAlphaBlend && (bAlpha || uFade < 255) ) {
- BLENDFUNCTION bf = { AC_SRC_OVER, 0, uFade, AC_SRC_ALPHA };
- // middle
- if( !bHole ) {
- rcDest.left = rc.left + rcScale9.left;
- rcDest.top = rc.top + rcScale9.top;
- rcDest.right = rc.right - rc.left - rcScale9.left - rcScale9.right;
- rcDest.bottom = rc.bottom - rc.top - rcScale9.top - rcScale9.bottom;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- if( !bTiledX && !bTiledY ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.left + rcScale9.left, rcBmpPart.top + rcScale9.top, \
- rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right, \
- rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom, bf);
- }
- else if( bTiledX && bTiledY ) {
- LONG lWidth = rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right;
- LONG lHeight = rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom;
- int iTimesX = (rcDest.right - rcDest.left + lWidth - 1) / lWidth;
- int iTimesY = (rcDest.bottom - rcDest.top + lHeight - 1) / lHeight;
- for( int j = 0; j < iTimesY; ++j ) {
- LONG lDestTop = rcDest.top + lHeight * j;
- LONG lDestBottom = rcDest.top + lHeight * (j + 1);
- LONG lDrawHeight = lHeight;
- if( lDestBottom > rcDest.bottom ) {
- lDrawHeight -= lDestBottom - rcDest.bottom;
- lDestBottom = rcDest.bottom;
- }
- for( int i = 0; i < iTimesX; ++i ) {
- LONG lDestLeft = rcDest.left + lWidth * i;
- LONG lDestRight = rcDest.left + lWidth * (i + 1);
- LONG lDrawWidth = lWidth;
- if( lDestRight > rcDest.right ) {
- lDrawWidth -= lDestRight - rcDest.right;
- lDestRight = rcDest.right;
- }
- lpAlphaBlend(hDC, rcDest.left + lWidth * i, rcDest.top + lHeight * j,
- lDestRight - lDestLeft, lDestBottom - lDestTop, hCloneDC,
- rcBmpPart.left + rcScale9.left, rcBmpPart.top + rcScale9.top, lDrawWidth, lDrawHeight, bf);
- }
- }
- }
- else if( bTiledX ) {
- LONG lWidth = rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right;
- int iTimes = (rcDest.right - rcDest.left + lWidth - 1) / lWidth;
- for( int i = 0; i < iTimes; ++i ) {
- LONG lDestLeft = rcDest.left + lWidth * i;
- LONG lDestRight = rcDest.left + lWidth * (i + 1);
- LONG lDrawWidth = lWidth;
- if( lDestRight > rcDest.right ) {
- lDrawWidth -= lDestRight - rcDest.right;
- lDestRight = rcDest.right;
- }
- rcDest.bottom -= rcDest.top;
- lpAlphaBlend(hDC, lDestLeft, rcDest.top, lDestRight - lDestLeft, rcDest.bottom,
- hCloneDC, rcBmpPart.left + rcScale9.left, rcBmpPart.top + rcScale9.top, \
- lDrawWidth, rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom, bf);
- }
- }
- else { // bTiledY
- LONG lHeight = rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom;
- int iTimes = (rcDest.bottom - rcDest.top + lHeight - 1) / lHeight;
- for( int i = 0; i < iTimes; ++i ) {
- LONG lDestTop = rcDest.top + lHeight * i;
- LONG lDestBottom = rcDest.top + lHeight * (i + 1);
- LONG lDrawHeight = lHeight;
- if( lDestBottom > rcDest.bottom ) {
- lDrawHeight -= lDestBottom - rcDest.bottom;
- lDestBottom = rcDest.bottom;
- }
- rcDest.right -= rcDest.left;
- lpAlphaBlend(hDC, rcDest.left, rcDest.top + lHeight * i, rcDest.right, lDestBottom - lDestTop,
- hCloneDC, rcBmpPart.left + rcScale9.left, rcBmpPart.top + rcScale9.top, \
- rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right, lDrawHeight, bf);
- }
- }
- }
- }
- // left-top
- if( rcScale9.left > 0 && rcScale9.top > 0 ) {
- rcDest.left = rc.left;
- rcDest.top = rc.top;
- rcDest.right = rcScale9.left;
- rcDest.bottom = rcScale9.top;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.left, rcBmpPart.top, rcScale9.left, rcScale9.top, bf);
- }
- }
- // top
- if( rcScale9.top > 0 ) {
- rcDest.left = rc.left + rcScale9.left;
- rcDest.top = rc.top;
- rcDest.right = rc.right - rc.left - rcScale9.left - rcScale9.right;
- rcDest.bottom = rcScale9.top;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.left + rcScale9.left, rcBmpPart.top, rcBmpPart.right - rcBmpPart.left - \
- rcScale9.left - rcScale9.right, rcScale9.top, bf);
- }
- }
- // right-top
- if( rcScale9.right > 0 && rcScale9.top > 0 ) {
- rcDest.left = rc.right - rcScale9.right;
- rcDest.top = rc.top;
- rcDest.right = rcScale9.right;
- rcDest.bottom = rcScale9.top;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.right - rcScale9.right, rcBmpPart.top, rcScale9.right, rcScale9.top, bf);
- }
- }
- // left
- if( rcScale9.left > 0 ) {
- rcDest.left = rc.left;
- rcDest.top = rc.top + rcScale9.top;
- rcDest.right = rcScale9.left;
- rcDest.bottom = rc.bottom - rc.top - rcScale9.top - rcScale9.bottom;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.left, rcBmpPart.top + rcScale9.top, rcScale9.left, rcBmpPart.bottom - \
- rcBmpPart.top - rcScale9.top - rcScale9.bottom, bf);
- }
- }
- // right
- if( rcScale9.right > 0 ) {
- rcDest.left = rc.right - rcScale9.right;
- rcDest.top = rc.top + rcScale9.top;
- rcDest.right = rcScale9.right;
- rcDest.bottom = rc.bottom - rc.top - rcScale9.top - rcScale9.bottom;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.right - rcScale9.right, rcBmpPart.top + rcScale9.top, rcScale9.right, \
- rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom, bf);
- }
- }
- // left-bottom
- if( rcScale9.left > 0 && rcScale9.bottom > 0 ) {
- rcDest.left = rc.left;
- rcDest.top = rc.bottom - rcScale9.bottom;
- rcDest.right = rcScale9.left;
- rcDest.bottom = rcScale9.bottom;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.left, rcBmpPart.bottom - rcScale9.bottom, rcScale9.left, rcScale9.bottom, bf);
- }
- }
- // bottom
- if( rcScale9.bottom > 0 ) {
- rcDest.left = rc.left + rcScale9.left;
- rcDest.top = rc.bottom - rcScale9.bottom;
- rcDest.right = rc.right - rc.left - rcScale9.left - rcScale9.right;
- rcDest.bottom = rcScale9.bottom;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.left + rcScale9.left, rcBmpPart.bottom - rcScale9.bottom, \
- rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right, rcScale9.bottom, bf);
- }
- }
- // right-bottom
- if( rcScale9.right > 0 && rcScale9.bottom > 0 ) {
- rcDest.left = rc.right - rcScale9.right;
- rcDest.top = rc.bottom - rcScale9.bottom;
- rcDest.right = rcScale9.right;
- rcDest.bottom = rcScale9.bottom;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- lpAlphaBlend(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.right - rcScale9.right, rcBmpPart.bottom - rcScale9.bottom, rcScale9.right, \
- rcScale9.bottom, bf);
- }
- }
- }
- else
- {
- if (rc.right - rc.left == rcBmpPart.right - rcBmpPart.left \
- && rc.bottom - rc.top == rcBmpPart.bottom - rcBmpPart.top \
- && rcScale9.left == 0 && rcScale9.right == 0 && rcScale9.top == 0 && rcScale9.bottom == 0)
- {
- if( ::IntersectRect(&rcTemp, &rcPaint, &rc) ) {
- ::BitBlt(hDC, rcTemp.left, rcTemp.top, rcTemp.right - rcTemp.left, rcTemp.bottom - rcTemp.top, \
- hCloneDC, rcBmpPart.left + rcTemp.left - rc.left, rcBmpPart.top + rcTemp.top - rc.top, SRCCOPY);
- }
- }
- else
- {
- // middle
- if( !bHole ) {
- rcDest.left = rc.left + rcScale9.left;
- rcDest.top = rc.top + rcScale9.top;
- rcDest.right = rc.right - rc.left - rcScale9.left - rcScale9.right;
- rcDest.bottom = rc.bottom - rc.top - rcScale9.top - rcScale9.bottom;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- if( !bTiledX && !bTiledY ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.left + rcScale9.left, rcBmpPart.top + rcScale9.top, \
- rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right, \
- rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom, SRCCOPY);
- }
- else if( bTiledX && bTiledY ) {
- LONG lWidth = rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right;
- LONG lHeight = rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom;
- int iTimesX = (rcDest.right - rcDest.left + lWidth - 1) / lWidth;
- int iTimesY = (rcDest.bottom - rcDest.top + lHeight - 1) / lHeight;
- for( int j = 0; j < iTimesY; ++j ) {
- LONG lDestTop = rcDest.top + lHeight * j;
- LONG lDestBottom = rcDest.top + lHeight * (j + 1);
- LONG lDrawHeight = lHeight;
- if( lDestBottom > rcDest.bottom ) {
- lDrawHeight -= lDestBottom - rcDest.bottom;
- lDestBottom = rcDest.bottom;
- }
- for( int i = 0; i < iTimesX; ++i ) {
- LONG lDestLeft = rcDest.left + lWidth * i;
- LONG lDestRight = rcDest.left + lWidth * (i + 1);
- LONG lDrawWidth = lWidth;
- if( lDestRight > rcDest.right ) {
- lDrawWidth -= lDestRight - rcDest.right;
- lDestRight = rcDest.right;
- }
- ::BitBlt(hDC, rcDest.left + lWidth * i, rcDest.top + lHeight * j, \
- lDestRight - lDestLeft, lDestBottom - lDestTop, hCloneDC, \
- rcBmpPart.left + rcScale9.left, rcBmpPart.top + rcScale9.top, SRCCOPY);
- }
- }
- }
- else if( bTiledX ) {
- LONG lWidth = rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right;
- int iTimes = (rcDest.right - rcDest.left + lWidth - 1) / lWidth;
- for( int i = 0; i < iTimes; ++i ) {
- LONG lDestLeft = rcDest.left + lWidth * i;
- LONG lDestRight = rcDest.left + lWidth * (i + 1);
- LONG lDrawWidth = lWidth;
- if( lDestRight > rcDest.right ) {
- lDrawWidth -= lDestRight - rcDest.right;
- lDestRight = rcDest.right;
- }
- rcDest.bottom -= rcDest.top;
- ::StretchBlt(hDC, lDestLeft, rcDest.top, lDestRight - lDestLeft, rcDest.bottom,
- hCloneDC, rcBmpPart.left + rcScale9.left, rcBmpPart.top + rcScale9.top, \
- lDrawWidth, rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom, SRCCOPY);
- }
- }
- else { // bTiledY
- LONG lHeight = rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom;
- int iTimes = (rcDest.bottom - rcDest.top + lHeight - 1) / lHeight;
- for( int i = 0; i < iTimes; ++i ) {
- LONG lDestTop = rcDest.top + lHeight * i;
- LONG lDestBottom = rcDest.top + lHeight * (i + 1);
- LONG lDrawHeight = lHeight;
- if( lDestBottom > rcDest.bottom ) {
- lDrawHeight -= lDestBottom - rcDest.bottom;
- lDestBottom = rcDest.bottom;
- }
- rcDest.right -= rcDest.left;
- ::StretchBlt(hDC, rcDest.left, rcDest.top + lHeight * i, rcDest.right, lDestBottom - lDestTop,
- hCloneDC, rcBmpPart.left + rcScale9.left, rcBmpPart.top + rcScale9.top, \
- rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right, lDrawHeight, SRCCOPY);
- }
- }
- }
- }
- // left-top
- if( rcScale9.left > 0 && rcScale9.top > 0 ) {
- rcDest.left = rc.left;
- rcDest.top = rc.top;
- rcDest.right = rcScale9.left;
- rcDest.bottom = rcScale9.top;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.left, rcBmpPart.top, rcScale9.left, rcScale9.top, SRCCOPY);
- }
- }
- // top
- if( rcScale9.top > 0 ) {
- rcDest.left = rc.left + rcScale9.left;
- rcDest.top = rc.top;
- rcDest.right = rc.right - rc.left - rcScale9.left - rcScale9.right;
- rcDest.bottom = rcScale9.top;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.left + rcScale9.left, rcBmpPart.top, rcBmpPart.right - rcBmpPart.left - \
- rcScale9.left - rcScale9.right, rcScale9.top, SRCCOPY);
- }
- }
- // right-top
- if( rcScale9.right > 0 && rcScale9.top > 0 ) {
- rcDest.left = rc.right - rcScale9.right;
- rcDest.top = rc.top;
- rcDest.right = rcScale9.right;
- rcDest.bottom = rcScale9.top;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.right - rcScale9.right, rcBmpPart.top, rcScale9.right, rcScale9.top, SRCCOPY);
- }
- }
- // left
- if( rcScale9.left > 0 ) {
- rcDest.left = rc.left;
- rcDest.top = rc.top + rcScale9.top;
- rcDest.right = rcScale9.left;
- rcDest.bottom = rc.bottom - rc.top - rcScale9.top - rcScale9.bottom;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.left, rcBmpPart.top + rcScale9.top, rcScale9.left, rcBmpPart.bottom - \
- rcBmpPart.top - rcScale9.top - rcScale9.bottom, SRCCOPY);
- }
- }
- // right
- if( rcScale9.right > 0 ) {
- rcDest.left = rc.right - rcScale9.right;
- rcDest.top = rc.top + rcScale9.top;
- rcDest.right = rcScale9.right;
- rcDest.bottom = rc.bottom - rc.top - rcScale9.top - rcScale9.bottom;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.right - rcScale9.right, rcBmpPart.top + rcScale9.top, rcScale9.right, \
- rcBmpPart.bottom - rcBmpPart.top - rcScale9.top - rcScale9.bottom, SRCCOPY);
- }
- }
- // left-bottom
- if( rcScale9.left > 0 && rcScale9.bottom > 0 ) {
- rcDest.left = rc.left;
- rcDest.top = rc.bottom - rcScale9.bottom;
- rcDest.right = rcScale9.left;
- rcDest.bottom = rcScale9.bottom;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.left, rcBmpPart.bottom - rcScale9.bottom, rcScale9.left, rcScale9.bottom, SRCCOPY);
- }
- }
- // bottom
- if( rcScale9.bottom > 0 ) {
- rcDest.left = rc.left + rcScale9.left;
- rcDest.top = rc.bottom - rcScale9.bottom;
- rcDest.right = rc.right - rc.left - rcScale9.left - rcScale9.right;
- rcDest.bottom = rcScale9.bottom;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.left + rcScale9.left, rcBmpPart.bottom - rcScale9.bottom, \
- rcBmpPart.right - rcBmpPart.left - rcScale9.left - rcScale9.right, rcScale9.bottom, SRCCOPY);
- }
- }
- // right-bottom
- if( rcScale9.right > 0 && rcScale9.bottom > 0 ) {
- rcDest.left = rc.right - rcScale9.right;
- rcDest.top = rc.bottom - rcScale9.bottom;
- rcDest.right = rcScale9.right;
- rcDest.bottom = rcScale9.bottom;
- rcDest.right += rcDest.left;
- rcDest.bottom += rcDest.top;
- if( ::IntersectRect(&rcTemp, &rcPaint, &rcDest) ) {
- rcDest.right -= rcDest.left;
- rcDest.bottom -= rcDest.top;
- ::StretchBlt(hDC, rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, hCloneDC, \
- rcBmpPart.right - rcScale9.right, rcBmpPart.bottom - rcScale9.bottom, rcScale9.right, \
- rcScale9.bottom, SRCCOPY);
- }
- }
- }
- }
- ::SelectObject(hCloneDC, hOldBitmap);
- ::DeleteDC(hCloneDC);
- }
- bool CRenderEngine::DrawImage(HDC hDC, CPaintManagerUI* pManager, const RECT& rcItem, const RECT& rcPaint,
- TDrawInfo& drawInfo)
- {
- // 1、aaa.jpg
- // 2、file='aaa.jpg' res='' restype='0' dest='0,0,0,0' source='0,0,0,0' scale9='0,0,0,0'
- // mask='#FF0000' fade='255' hole='false' xtiled='false' ytiled='false' hsl='false'
- if( pManager == NULL ) return true;
- if( drawInfo.pImageInfo == NULL ) {
- if( drawInfo.bLoaded ) return false;
- drawInfo.bLoaded = true;
- if( drawInfo.sDrawString.IsEmpty() ) return false;
- bool bUseRes = false;
- CDuiString sImageName = drawInfo.sDrawString;
- CDuiString sImageResType;
- DWORD dwMask = 0;
- bool bUseHSL = false;
- CDuiString sItem;
- CDuiString sValue;
- LPTSTR pstr = NULL;
- LPCTSTR pstrImage = drawInfo.sDrawString.GetData();
- while( *pstrImage != _T('\0') ) {
- sItem.Empty();
- sValue.Empty();
- while( *pstrImage > _T('\0') && *pstrImage <= _T(' ') ) pstrImage = ::CharNext(pstrImage);
- while( *pstrImage != _T('\0') && *pstrImage != _T('=') && *pstrImage > _T(' ') ) {
- LPTSTR pstrTemp = ::CharNext(pstrImage);
- while( pstrImage < pstrTemp) {
- sItem += *pstrImage++;
- }
- }
- while( *pstrImage > _T('\0') && *pstrImage <= _T(' ') ) pstrImage = ::CharNext(pstrImage);
- if( *pstrImage++ != _T('=') ) break;
- while( *pstrImage > _T('\0') && *pstrImage <= _T(' ') ) pstrImage = ::CharNext(pstrImage);
- if( *pstrImage++ != _T('\'') ) break;
- while( *pstrImage != _T('\0') && *pstrImage != _T('\'') ) {
- LPTSTR pstrTemp = ::CharNext(pstrImage);
- while( pstrImage < pstrTemp) {
- sValue += *pstrImage++;
- }
- }
- if( *pstrImage++ != _T('\'') ) break;
- if( !sValue.IsEmpty() ) {
- if( sItem == _T("file") ) {
- sImageName = sValue;
- }
- else if( sItem == _T("res") ) {
- bUseRes = true;
- sImageName = sValue;
- }
- else if( sItem == _T("restype") ) {
- sImageResType = sValue;
- }
- else if (sItem == _T("color")) {
- bUseRes = true;
- sImageResType = RES_TYPE_COLOR;
- sImageName = sValue;
- }
- else if( sItem == _T("dest") ) {
- drawInfo.rcDestOffset.left = _tcstol(sValue.GetData(), &pstr, 10); ASSERT(pstr);
- drawInfo.rcDestOffset.top = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
- drawInfo.rcDestOffset.right = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
- drawInfo.rcDestOffset.bottom = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
- }
- else if( sItem == _T("source") ) {
- drawInfo.rcBmpPart.left = _tcstol(sValue.GetData(), &pstr, 10); ASSERT(pstr);
- drawInfo.rcBmpPart.top = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
- drawInfo.rcBmpPart.right = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
- drawInfo.rcBmpPart.bottom = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
- }
- else if( sItem == _T("corner") || sItem == _T("scale9")) {
- drawInfo.rcScale9.left = _tcstol(sValue.GetData(), &pstr, 10); ASSERT(pstr);
- drawInfo.rcScale9.top = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
- drawInfo.rcScale9.right = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
- drawInfo.rcScale9.bottom = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
- }
- else if( sItem == _T("mask") ) {
- if( sValue[0] == _T('#')) dwMask = _tcstoul(sValue.GetData() + 1, &pstr, 16);
- else dwMask = _tcstoul(sValue.GetData(), &pstr, 16);
- }
- else if( sItem == _T("fade") ) {
- drawInfo.uFade = (BYTE)_tcstoul(sValue.GetData(), &pstr, 10);
- }
- else if( sItem == _T("hole") ) {
- drawInfo.bHole = (_tcscmp(sValue.GetData(), _T("true")) == 0);
- }
- else if( sItem == _T("xtiled") ) {
- drawInfo.bTiledX = (_tcscmp(sValue.GetData(), _T("true")) == 0);
- }
- else if( sItem == _T("ytiled") ) {
- drawInfo.bTiledY = (_tcscmp(sValue.GetData(), _T("true")) == 0);
- }
- else if( sItem == _T("hsl") ) {
- bUseHSL = (_tcscmp(sValue.GetData(), _T("true")) == 0);
- }
- }
- if( *pstrImage++ != _T(' ') ) break;
- }
- drawInfo.sImageName = sImageName;
- const TImageInfo* data = NULL;
- if( bUseRes == false ) {
- data = pManager->GetImageEx((LPCTSTR)sImageName, NULL, dwMask, bUseHSL);
- }
- else {
- data = pManager->GetImageEx((LPCTSTR)sImageName, (LPCTSTR)sImageResType, dwMask, bUseHSL);
- }
- if( !data ) return false;
- drawInfo.pImageInfo = data;
- if( drawInfo.rcBmpPart.left == 0 && drawInfo.rcBmpPart.right == 0 &&
- drawInfo.rcBmpPart.top == 0 && drawInfo.rcBmpPart.bottom == 0 ) {
- drawInfo.rcBmpPart.right = data->nX;
- drawInfo.rcBmpPart.bottom = data->nY;
- }
- }
- if( drawInfo.rcBmpPart.right > drawInfo.pImageInfo->nX ) drawInfo.rcBmpPart.right = drawInfo.pImageInfo->nX;
- if( drawInfo.rcBmpPart.bottom > drawInfo.pImageInfo->nY ) drawInfo.rcBmpPart.bottom = drawInfo.pImageInfo->nY;
- if( hDC == NULL ) return true;
- RECT rcDest = rcItem;
- if( drawInfo.rcDestOffset.left != 0 || drawInfo.rcDestOffset.top != 0 ||
- drawInfo.rcDestOffset.right != 0 || drawInfo.rcDestOffset.bottom != 0 ) {
- rcDest.left = rcItem.left + drawInfo.rcDestOffset.left;
- rcDest.top = rcItem.top + drawInfo.rcDestOffset.top;
- rcDest.right = rcItem.left + drawInfo.rcDestOffset.right;
- if( rcDest.right > rcItem.right ) rcDest.right = rcItem.right;
- rcDest.bottom = rcItem.top + drawInfo.rcDestOffset.bottom;
- if( rcDest.bottom > rcItem.bottom ) rcDest.bottom = rcItem.bottom;
- }
- RECT rcTemp;
- if( !::IntersectRect(&rcTemp, &rcDest, &rcItem) ) return true;
- if( !::IntersectRect(&rcTemp, &rcDest, &rcPaint) ) return true;
- DrawImage(hDC, drawInfo.pImageInfo->hBitmap, rcDest, rcPaint, drawInfo.rcBmpPart, drawInfo.rcScale9,
- drawInfo.pImageInfo->bAlpha, drawInfo.uFade, drawInfo.bHole, drawInfo.bTiledX, drawInfo.bTiledY);
- return true;
- }
- void CRenderEngine::DrawColor(HDC hDC, const RECT& rc, DWORD color)
- {
- if( color <= 0x00FFFFFF ) return;
- if( color >= 0xFF000000 )
- {
- ::SetBkColor(hDC, RGB(GetBValue(color), GetGValue(color), GetRValue(color)));
- ::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
- }
- else
- {
- // Create a new 32bpp bitmap with room for an alpha channel
- BITMAPINFO bmi = { 0 };
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = 1;
- bmi.bmiHeader.biHeight = 1;
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
- bmi.bmiHeader.biSizeImage = 1 * 1 * sizeof(DWORD);
- LPDWORD pDest = NULL;
- HBITMAP hBitmap = ::CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (LPVOID*) &pDest, NULL, 0);
- if( !hBitmap ) return;
- *pDest = color;
- RECT rcBmpPart = {0, 0, 1, 1};
- RECT rcCorners = {0};
- DrawImage(hDC, hBitmap, rc, rc, rcBmpPart, rcCorners, true, 255);
- ::DeleteObject(hBitmap);
- }
- }
- void CRenderEngine::DrawGradient(HDC hDC, const RECT& rc, DWORD dwFirst, DWORD dwSecond, bool bVertical, int nSteps)
- {
- typedef BOOL (WINAPI *LPALPHABLEND)(HDC, int, int, int, int,HDC, int, int, int, int, BLENDFUNCTION);
- static LPALPHABLEND lpAlphaBlend = (LPALPHABLEND) ::GetProcAddress(::GetModuleHandle(_T("msimg32.dll")), "AlphaBlend");
- if( lpAlphaBlend == NULL ) lpAlphaBlend = AlphaBitBlt;
- typedef BOOL (WINAPI *PGradientFill)(HDC, PTRIVERTEX, ULONG, PVOID, ULONG, ULONG);
- static PGradientFill lpGradientFill = (PGradientFill) ::GetProcAddress(::GetModuleHandle(_T("msimg32.dll")), "GradientFill");
- BYTE bAlpha = (BYTE)(((dwFirst >> 24) + (dwSecond >> 24)) >> 1);
- if( bAlpha == 0 ) return;
- int cx = rc.right - rc.left;
- int cy = rc.bottom - rc.top;
- RECT rcPaint = rc;
- HDC hPaintDC = hDC;
- HBITMAP hPaintBitmap = NULL;
- HBITMAP hOldPaintBitmap = NULL;
- if( bAlpha < 255 ) {
- rcPaint.left = rcPaint.top = 0;
- rcPaint.right = cx;
- rcPaint.bottom = cy;
- hPaintDC = ::CreateCompatibleDC(hDC);
- hPaintBitmap = ::CreateCompatibleBitmap(hDC, cx, cy);
- ASSERT(hPaintDC);
- ASSERT(hPaintBitmap);
- hOldPaintBitmap = (HBITMAP) ::SelectObject(hPaintDC, hPaintBitmap);
- }
- if( lpGradientFill != NULL )
- {
- TRIVERTEX triv[2] =
- {
- { rcPaint.left, rcPaint.top, GetBValue(dwFirst) << 8, GetGValue(dwFirst) << 8, GetRValue(dwFirst) << 8, 0xFF00 },
- { rcPaint.right, rcPaint.bottom, GetBValue(dwSecond) << 8, GetGValue(dwSecond) << 8, GetRValue(dwSecond) << 8, 0xFF00 }
- };
- GRADIENT_RECT grc = { 0, 1 };
- lpGradientFill(hPaintDC, triv, 2, &grc, 1, bVertical ? GRADIENT_FILL_RECT_V : GRADIENT_FILL_RECT_H);
- }
- else
- {
- // Determine how many shades
- int nShift = 1;
- if( nSteps >= 64 ) nShift = 6;
- else if( nSteps >= 32 ) nShift = 5;
- else if( nSteps >= 16 ) nShift = 4;
- else if( nSteps >= 8 ) nShift = 3;
- else if( nSteps >= 4 ) nShift = 2;
- int nLines = 1 << nShift;
- for( int i = 0; i < nLines; i++ ) {
- // Do a little alpha blending
- BYTE bR = (BYTE) ((GetBValue(dwSecond) * (nLines - i) + GetBValue(dwFirst) * i) >> nShift);
- BYTE bG = (BYTE) ((GetGValue(dwSecond) * (nLines - i) + GetGValue(dwFirst) * i) >> nShift);
- BYTE bB = (BYTE) ((GetRValue(dwSecond) * (nLines - i) + GetRValue(dwFirst) * i) >> nShift);
- // ... then paint with the resulting color
- HBRUSH hBrush = ::CreateSolidBrush(RGB(bR,bG,bB));
- RECT r2 = rcPaint;
- if( bVertical ) {
- r2.bottom = rc.bottom - ((i * (rc.bottom - rc.top)) >> nShift);
- r2.top = rc.bottom - (((i + 1) * (rc.bottom - rc.top)) >> nShift);
- if( (r2.bottom - r2.top) > 0 ) ::FillRect(hDC, &r2, hBrush);
- }
- else {
- r2.left = rc.right - (((i + 1) * (rc.right - rc.left)) >> nShift);
- r2.right = rc.right - ((i * (rc.right - rc.left)) >> nShift);
- if( (r2.right - r2.left) > 0 ) ::FillRect(hPaintDC, &r2, hBrush);
- }
- ::DeleteObject(hBrush);
- }
- }
- if( bAlpha < 255 ) {
- BLENDFUNCTION bf = { AC_SRC_OVER, 0, bAlpha, AC_SRC_ALPHA };
- lpAlphaBlend(hDC, rc.left, rc.top, cx, cy, hPaintDC, 0, 0, cx, cy, bf);
- ::SelectObject(hPaintDC, hOldPaintBitmap);
- ::DeleteObject(hPaintBitmap);
- ::DeleteDC(hPaintDC);
- }
- }
- void CRenderEngine::DrawLine( HDC hDC, const RECT& rc, int nSize, DWORD dwPenColor, int nStyle)
- {
- ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
- LOGPEN lg;
- lg.lopnColor = RGB(GetBValue(dwPenColor), GetGValue(dwPenColor), GetRValue(dwPenColor));
- lg.lopnStyle = nStyle;
- lg.lopnWidth.x = nSize;
- HPEN hPen = CreatePenIndirect(&lg);
- HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen);
- POINT ptTemp = { 0 };
- ::MoveToEx(hDC, rc.left, rc.top, &ptTemp);
- ::LineTo(hDC, rc.right, rc.bottom);
- ::SelectObject(hDC, hOldPen);
- ::DeleteObject(hPen);
- }
- void CRenderEngine::DrawRect(HDC hDC, const RECT& rc, int nSize, DWORD dwPenColor, int nStyle)
- {
- ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
- HPEN hPen = ::CreatePen(nStyle | PS_INSIDEFRAME, nSize, RGB(GetBValue(dwPenColor), GetGValue(dwPenColor), GetRValue(dwPenColor)));
- HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen);
- ::SelectObject(hDC, ::GetStockObject(HOLLOW_BRUSH));
- ::Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
- ::SelectObject(hDC, hOldPen);
- ::DeleteObject(hPen);
- }
- void CRenderEngine::DrawRoundRect(HDC hDC, const RECT& rc, int nSize, int width, int height, DWORD dwPenColor, int nStyle)
- {
- ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
- HPEN hPen = ::CreatePen(nStyle | PS_INSIDEFRAME, nSize, RGB(GetBValue(dwPenColor), GetGValue(dwPenColor), GetRValue(dwPenColor)));
- HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen);
- ::SelectObject(hDC, ::GetStockObject(HOLLOW_BRUSH));
- ::RoundRect(hDC, rc.left, rc.top, rc.right, rc.bottom, width, height);
- ::SelectObject(hDC, hOldPen);
- ::DeleteObject(hPen);
- }
- void CRenderEngine::DrawText(HDC hDC, CPaintManagerUI* pManager, RECT& rc, LPCTSTR pstrText, DWORD dwTextColor, int iFont, UINT uStyle)
- {
- ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
- if( pstrText == NULL || pManager == NULL ) return;
- CDuiString sText = pstrText;
- CPaintManagerUI::ProcessMultiLanguageTokens(sText);
- pstrText = sText;
- ::SetBkMode(hDC, TRANSPARENT);
- ::SetTextColor(hDC, RGB(GetBValue(dwTextColor), GetGValue(dwTextColor), GetRValue(dwTextColor)));
- HFONT hOldFont = (HFONT)::SelectObject(hDC, pManager->GetFont(iFont));
- ::DrawText(hDC, pstrText, -1, &rc, uStyle | DT_NOPREFIX);
- ::SelectObject(hDC, hOldFont);
- }
- void CRenderEngine::DrawHtmlText(HDC hDC, CPaintManagerUI* pManager, RECT& rc, LPCTSTR pstrText, DWORD dwTextColor, RECT* prcLinks, CDuiString* sLinks, int& nLinkRects, int iDefaultFont, UINT uStyle)
- {
- // 考虑到在xml编辑器中使用<>符号不方便,可以使用{}符号代替
- // 支持标签嵌套(如<l><b>text</b></l>),但是交叉嵌套是应该避免的(如<l><b>text</l></b>)
- // The string formatter supports a kind of "mini-html" that consists of various short tags:
- //
- // Bold: <b>text</b>
- // Color: <c #xxxxxx>text</c> where x = RGB in hex
- // Font: <f x>text</f> where x = font id
- // Italic: <i>text</i>
- // Image: <i x y z> where x = image name and y = imagelist num and z(optional) = imagelist id
- // Link: <a x>text</a> where x(optional) = link content, normal like app:notepad or http:www.xxx.com
- // NewLine <n>
- // Paragraph: <p x>text</p> where x = extra pixels indent in p
- // Raw Text: <r>text</r>
- // Selected: <s>text</s>
- // Underline: <u>text</u>
- // X Indent: <x i> where i = hor indent in pixels
- // Y Indent: <y i> where i = ver indent in pixels
- // Vertical align <v x> where x = top or x = center or x = bottom
- ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
- if( pstrText == NULL || pManager == NULL ) return;
- if( ::IsRectEmpty(&rc) ) return;
- bool bDraw = (uStyle & DT_CALCRECT) == 0;
- CDuiPtrArray aFontArray(10);
- CDuiPtrArray aColorArray(10);
- CDuiPtrArray aPIndentArray(10);
- CDuiPtrArray aVAlignArray(10);
- RECT rcClip = { 0 };
- ::GetClipBox(hDC, &rcClip);
- HRGN hOldRgn = ::CreateRectRgnIndirect(&rcClip);
- HRGN hRgn = ::CreateRectRgnIndirect(&rc);
- if( bDraw ) ::ExtSelectClipRgn(hDC, hRgn, RGN_AND);
- CDuiString sText = pstrText;
- CPaintManagerUI::ProcessMultiLanguageTokens(sText);
- pstrText = sText;
- TEXTMETRIC* pTm = &pManager->GetFontInfo(iDefaultFont)->tm;
- HFONT hOldFont = (HFONT) ::SelectObject(hDC, pManager->GetFontInfo(iDefaultFont)->hFont);
- ::SetBkMode(hDC, TRANSPARENT);
- ::SetTextColor(hDC, RGB(GetBValue(dwTextColor), GetGValue(dwTextColor), GetRValue(dwTextColor)));
- DWORD dwBkColor = pManager->GetDefaultSelectedBkColor();
- ::SetBkColor(hDC, RGB(GetBValue(dwBkColor), GetGValue(dwBkColor), GetRValue(dwBkColor)));
- // If the drawstyle include a alignment, we'll need to first determine the text-size so
- // we can draw it at the correct position...
- if( ((uStyle & DT_CENTER) != 0 || (uStyle & DT_RIGHT) != 0 || (uStyle & DT_VCENTER) != 0 || (uStyle & DT_BOTTOM) != 0) && (uStyle & DT_CALCRECT) == 0 ) {
- RECT rcText = { 0, 0, 9999, 100 };
- if ((uStyle & DT_SINGLELINE) == 0) {
- rcText.right = rc.right - rc.left;
- rcText.bottom = rc.bottom - rc.top;
- }
- int nLinks = 0;
- DrawHtmlText(hDC, pManager, rcText, pstrText, dwTextColor, NULL, NULL, nLinks, iDefaultFont, uStyle | DT_CALCRECT & ~DT_CENTER & ~DT_RIGHT & ~DT_VCENTER & ~DT_BOTTOM);
- if( (uStyle & DT_SINGLELINE) != 0 ){
- if( (uStyle & DT_CENTER) != 0 ) {
- rc.left = rc.left + ((rc.right - rc.left) / 2) - ((rcText.right - rcText.left) / 2);
- rc.right = rc.left + (rcText.right - rcText.left);
- }
- if( (uStyle & DT_RIGHT) != 0 ) {
- rc.left = rc.right - (rcText.right - rcText.left);
- }
- }
- if( (uStyle & DT_VCENTER) != 0 ) {
- rc.top = rc.top + ((rc.bottom - rc.top) / 2) - ((rcText.bottom - rcText.top) / 2);
- rc.bottom = rc.top + (rcText.bottom - rcText.top);
- }
- if( (uStyle & DT_BOTTOM) != 0 ) {
- rc.top = rc.bottom - (rcText.bottom - rcText.top);
- }
- }
- bool bHoverLink = false;
- CDuiString sHoverLink;
- POINT ptMouse = pManager->GetMousePos();
- for( int i = 0; !bHoverLink && i < nLinkRects; i++ ) {
- if( ::PtInRect(prcLinks + i, ptMouse) ) {
- sHoverLink = *(CDuiString*)(sLinks + i);
- bHoverLink = true;
- }
- }
- POINT pt = { rc.left, rc.top };
- int iLinkIndex = 0;
- int cxLine = 0;
- int cyLine = pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1);
- int cyMinHeight = 0;
- int cxMaxWidth = 0;
- POINT ptLinkStart = { 0 };
- bool bLineEnd = false;
- bool bInRaw = false;
- bool bInLink = false;
- bool bInSelected = false;
- int iLineLinkIndex = 0;
- // 排版习惯是图文底部对齐,所以每行绘制都要分两步,先计算高度,再绘制
- CDuiPtrArray aLineFontArray;
- CDuiPtrArray aLineColorArray;
- CDuiPtrArray aLinePIndentArray;
- CDuiPtrArray aLineVAlignArray;
- LPCTSTR pstrLineBegin = pstrText;
- bool bLineInRaw = false;
- bool bLineInLink = false;
- bool bLineInSelected = false;
- UINT iVAlign = DT_BOTTOM;
- int cxLineWidth = 0;
- int cyLineHeight = 0;
- int cxOffset = 0;
- bool bLineDraw = false; // 行的第二阶段:绘制
- while( *pstrText != _T('\0') ) {
- if( pt.x >= rc.right || *pstrText == _T('\n') || bLineEnd ) {
- if( *pstrText == _T('\n') ) pstrText++;
- if( bLineEnd ) bLineEnd = false;
- if( !bLineDraw ) {
- if( bInLink && iLinkIndex < nLinkRects ) {
- ::SetRect(&prcLinks[iLinkIndex++], ptLinkStart.x, ptLinkStart.y, MIN(pt.x, rc.right), pt.y + cyLine);
- CDuiString *pStr1 = (CDuiString*)(sLinks + iLinkIndex - 1);
- CDuiString *pStr2 = (CDuiString*)(sLinks + iLinkIndex);
- *pStr2 = *pStr1;
- }
- for( int i = iLineLinkIndex; i < iLinkIndex; i++ ) {
- prcLinks[i].bottom = pt.y + cyLine;
- }
- if( bDraw ) {
- bInLink = bLineInLink;
- iLinkIndex = iLineLinkIndex;
- }
- }
- else {
- if( bInLink && iLinkIndex < nLinkRects ) iLinkIndex++;
- bLineInLink = bInLink;
- iLineLinkIndex = iLinkIndex;
- }
- if( (uStyle & DT_SINGLELINE) != 0 && (!bDraw || bLineDraw) )
- break;
- if( bDraw ) bLineDraw = !bLineDraw; // !
- pt.x = rc.left;
- cxOffset = 0;
- if (bLineDraw) {
- if( (uStyle & DT_SINGLELINE) == 0 && (uStyle & DT_CENTER) != 0 ) {
- cxOffset = (rc.right - rc.left - cxLineWidth)/2;
- }
- else if( (uStyle & DT_SINGLELINE) == 0 && (uStyle & DT_RIGHT) != 0) {
- cxOffset = rc.right - rc.left - cxLineWidth;
- }
- }
- else {
- pt.y += cyLine;
- }
- if( pt.y > rc.bottom && bDraw )
- break;
- ptLinkStart = pt;
- cyLine = pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1);
- if( pt.x >= rc.right )
- break;
- }
- else if( !bInRaw && ( *pstrText == _T('<') || *pstrText == _T('{') )
- && ( pstrText[1] >= _T('a') && pstrText[1] <= _T('z') )
- && ( pstrText[2] == _T(' ') || pstrText[2] == _T('>') || pstrText[2] == _T('}') ) ) {
- pstrText++;
- LPCTSTR pstrNextStart = NULL;
- switch( *pstrText ) {
- case _T('a'): // Link
- {
- pstrText++;
- while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
- if( iLinkIndex < nLinkRects && !bLineDraw ) {
- CDuiString *pStr = (CDuiString*)(sLinks + iLinkIndex);
- pStr->Empty();
- while( *pstrText != _T('\0') && *pstrText != _T('>') && *pstrText != _T('}') ) {
- LPCTSTR pstrTemp = ::CharNext(pstrText);
- while( pstrText < pstrTemp) {
- *pStr += *pstrText++;
- }
- }
- }
- DWORD clrColor = pManager->GetDefaultLinkFontColor();
- if( bHoverLink && iLinkIndex < nLinkRects ) {
- CDuiString *pStr = (CDuiString*)(sLinks + iLinkIndex);
- if( sHoverLink == *pStr ) clrColor = pManager->GetDefaultLinkHoverFontColor();
- }
- //else if( prcLinks == NULL ) {
- // if( ::PtInRect(&rc, ptMouse) )
- // clrColor = pManager->GetDefaultLinkHoverFontColor();
- //}
- aColorArray.Add((LPVOID)clrColor);
- ::SetTextColor(hDC, RGB(GetBValue(clrColor), GetGValue(clrColor), GetRValue(clrColor)));
- TFontInfo* pFontInfo = pManager->GetFontInfo(iDefaultFont);
- if( aFontArray.GetSize() > 0 ) pFontInfo = (TFontInfo*)aFontArray.GetAt(aFontArray.GetSize() - 1);
- if( pFontInfo->bUnderline == false ) {
- HFONT hFont = pManager->GetFont(pFontInfo->sFontName, pFontInfo->iSize, pFontInfo->bBold, true, pFontInfo->bItalic);
- if( hFont == NULL ) {
- hFont = pManager->AddFont(g_iFontID, pFontInfo->sFontName, pFontInfo->iSize, pFontInfo->bBold, true, pFontInfo->bItalic);
- g_iFontID += 1;
- }
- pFontInfo = pManager->GetFontInfo(hFont);
- aFontArray.Add(pFontInfo);
- pTm = &pFontInfo->tm;
- ::SelectObject(hDC, pFontInfo->hFont);
- cyLine = MAX(cyLine, pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1));
- }
- ptLinkStart = pt;
- bInLink = true;
- }
- break;
- case _T('b'): // Bold
- {
- pstrText++;
- TFontInfo* pFontInfo = pManager->GetFontInfo(iDefaultFont);
- if( aFontArray.GetSize() > 0 ) pFontInfo = (TFontInfo*)aFontArray.GetAt(aFontArray.GetSize() - 1);
- if( pFontInfo->bBold == false ) {
- HFONT hFont = pManager->GetFont(pFontInfo->sFontName, pFontInfo->iSize, true, pFontInfo->bUnderline, pFontInfo->bItalic);
- if( hFont == NULL ) {
- hFont = pManager->AddFont(g_iFontID, pFontInfo->sFontName, pFontInfo->iSize, true, pFontInfo->bUnderline, pFontInfo->bItalic);
- g_iFontID += 1;
- }
- pFontInfo = pManager->GetFontInfo(hFont);
- aFontArray.Add(pFontInfo);
- pTm = &pFontInfo->tm;
- ::SelectObject(hDC, pFontInfo->hFont);
- cyLine = MAX(cyLine, pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1));
- }
- }
- break;
- case _T('c'): // Color
- {
- pstrText++;
- while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
- if( *pstrText == _T('#')) pstrText++;
- DWORD clrColor = _tcstol(pstrText, const_cast<LPTSTR*>(&pstrText), 16);
- aColorArray.Add((LPVOID)clrColor);
- ::SetTextColor(hDC, RGB(GetBValue(clrColor), GetGValue(clrColor), GetRValue(clrColor)));
- }
- break;
- case _T('f'): // Font
- {
- pstrText++;
- while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
- LPCTSTR pstrTemp = pstrText;
- int iFont = (int) _tcstol(pstrText, const_cast<LPTSTR*>(&pstrText), 10);
- //if( isdigit(*pstrText) ) { // debug版本会引起异常
- if( pstrTemp != pstrText ) {
- TFontInfo* pFontInfo = pManager->GetFontInfo(iFont);
- aFontArray.Add(pFontInfo);
- pTm = &pFontInfo->tm;
- ::SelectObject(hDC, pFontInfo->hFont);
- }
- else {
- CDuiString sFontName;
- int iFontSize = 10;
- CDuiString sFontAttr;
- bool bBold = false;
- bool bUnderline = false;
- bool bItalic = false;
- while( *pstrText != _T('\0') && *pstrText != _T('>') && *pstrText != _T('}') && *pstrText != _T(' ') ) {
- pstrTemp = ::CharNext(pstrText);
- while( pstrText < pstrTemp) {
- sFontName += *pstrText++;
- }
- }
- while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
- if( isdigit(*pstrText) ) {
- iFontSize = (int) _tcstol(pstrText, const_cast<LPTSTR*>(&pstrText), 10);
- }
- while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
- while( *pstrText != _T('\0') && *pstrText != _T('>') && *pstrText != _T('}') ) {
- pstrTemp = ::CharNext(pstrText);
- while( pstrText < pstrTemp) {
- sFontAttr += *pstrText++;
- }
- }
- sFontAttr.MakeLower();
- if( sFontAttr.Find(_T("bold")) >= 0 ) bBold = true;
- if( sFontAttr.Find(_T("underline")) >= 0 ) bUnderline = true;
- if( sFontAttr.Find(_T("italic")) >= 0 ) bItalic = true;
- HFONT hFont = pManager->GetFont(sFontName, iFontSize, bBold, bUnderline, bItalic);
- if( hFont == NULL ) {
- hFont = pManager->AddFont(g_iFontID, sFontName, iFontSize, bBold, bUnderline, bItalic);
- g_iFontID += 1;
- }
- TFontInfo* pFontInfo = pManager->GetFontInfo(hFont);
- aFontArray.Add(pFontInfo);
- pTm = &pFontInfo->tm;
- ::SelectObject(hDC, pFontInfo->hFont);
- }
- cyLine = MAX(cyLine, pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1));
- }
- break;
- case _T('i'): // Italic or Image
- {
- pstrNextStart = pstrText - 1;
- pstrText++;
- CDuiString sImageString = pstrText;
- int iWidth = 0;
- int iHeight = 0;
- while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
- const TImageInfo* pImageInfo = NULL;
- CDuiString sName;
- while( *pstrText != _T('\0') && *pstrText != _T('>') && *pstrText != _T('}') && *pstrText != _T(' ') ) {
- LPCTSTR pstrTemp = ::CharNext(pstrText);
- while( pstrText < pstrTemp) {
- sName += *pstrText++;
- }
- }
- if( sName.IsEmpty() ) { // Italic
- pstrNextStart = NULL;
- TFontInfo* pFontInfo = pManager->GetFontInfo(iDefaultFont);
- if( aFontArray.GetSize() > 0 ) pFontInfo = (TFontInfo*)aFontArray.GetAt(aFontArray.GetSize() - 1);
- if( pFontInfo->bItalic == false ) {
- HFONT hFont = pManager->GetFont(pFontInfo->sFontName, pFontInfo->iSize, pFontInfo->bBold, pFontInfo->bUnderline, true);
- if( hFont == NULL ) {
- hFont = pManager->AddFont(g_iFontID, pFontInfo->sFontName, pFontInfo->iSize, pFontInfo->bBold, pFontInfo->bUnderline, true);
- g_iFontID += 1;
- }
- pFontInfo = pManager->GetFontInfo(hFont);
- aFontArray.Add(pFontInfo);
- pTm = &pFontInfo->tm;
- ::SelectObject(hDC, pFontInfo->hFont);
- cyLine = MAX(cyLine, pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1));
- }
- }
- else {
- while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
- int iImageListNum = (int) _tcstol(pstrText, const_cast<LPTSTR*>(&pstrText), 10);
- if( iImageListNum <= 0 ) iImageListNum = 1;
- while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
- int iImageListIndex = (int) _tcstol(pstrText, const_cast<LPTSTR*>(&pstrText), 10);
- if( iImageListIndex < 0 || iImageListIndex >= iImageListNum ) iImageListIndex = 0;
- if( _tcsstr(sImageString.GetData(), _T("file=\'")) != NULL || _tcsstr(sImageString.GetData(), _T("res=\'")) != NULL ) {
- CDuiString sImageResType;
- CDuiString sImageName;
- LPCTSTR pStrImage = sImageString.GetData();
- CDuiString sItem;
- CDuiString sValue;
- while( *pStrImage != _T('\0') ) {
- sItem.Empty();
- sValue.Empty();
- while( *pStrImage > _T('\0') && *pStrImage <= _T(' ') ) pStrImage = ::CharNext(pStrImage);
- while( *pStrImage != _T('\0') && *pStrImage != _T('=') && *pStrImage > _T(' ') ) {
- LPTSTR pstrTemp = ::CharNext(pStrImage);
- while( pStrImage < pstrTemp) {
- sItem += *pStrImage++;
- }
- }
- while( *pStrImage > _T('\0') && *pStrImage <= _T(' ') ) pStrImage = ::CharNext(pStrImage);
- if( *pStrImage++ != _T('=') ) break;
- while( *pStrImage > _T('\0') && *pStrImage <= _T(' ') ) pStrImage = ::CharNext(pStrImage);
- if( *pStrImage++ != _T('\'') ) break;
- while( *pStrImage != _T('\0') && *pStrImage != _T('\'') ) {
- LPTSTR pstrTemp = ::CharNext(pStrImage);
- while( pStrImage < pstrTemp) {
- sValue += *pStrImage++;
- }
- }
- if( *pStrImage++ != _T('\'') ) break;
- if( !sValue.IsEmpty() ) {
- if( sItem == _T("file") || sItem == _T("res") ) {
- sImageName = sValue;
- }
- else if( sItem == _T("restype") ) {
- sImageResType = sValue;
- }
- }
- if( *pStrImage++ != _T(' ') ) break;
- }
- pImageInfo = pManager->GetImageEx((LPCTSTR)sImageName, sImageResType);
- }
- else
- pImageInfo = pManager->GetImageEx((LPCTSTR)sName);
- if( pImageInfo ) {
- iWidth = pImageInfo->nX;
- iHeight = pImageInfo->nY;
- if( iImageListNum > 1 ) iWidth /= iImageListNum;
- if( pt.x + iWidth > rc.right && pt.x > rc.left && (uStyle & DT_SINGLELINE) == 0 ) {
- bLineEnd = true;
- cxLine = pt.x - rc.left;
- }
- else {
- pstrNextStart = NULL;
- if( bDraw && bLineDraw ) {
- CDuiRect rcImage(pt.x + cxOffset, pt.y + cyLineHeight - iHeight, pt.x + + cxOffset + iWidth, pt.y + cyLineHeight);
- iVAlign = DT_BOTTOM;
- if (aVAlignArray.GetSize() > 0) iVAlign = (UINT)aVAlignArray.GetAt(aVAlignArray.GetSize() - 1);
- if (iVAlign == DT_VCENTER) {
- if( iHeight < cyLineHeight ) {
- rcImage.bottom -= (cyLineHeight - iHeight) / 2;
- rcImage.top = rcImage.bottom - iHeight;
- }
- }
- else if (iVAlign == DT_TOP) {
- if( iHeight < cyLineHeight ) {
- rcImage.bottom = pt.y + iHeight;
- rcImage.top = pt.y;
- }
- }
- CDuiRect rcBmpPart(0, 0, iWidth, iHeight);
- rcBmpPart.left = iWidth * iImageListIndex;
- rcBmpPart.right = iWidth * (iImageListIndex + 1);
- CDuiRect rcCorner(0, 0, 0, 0);
- DrawImage(hDC, pImageInfo->hBitmap, rcImage, rcImage, rcBmpPart, rcCorner, \
- pImageInfo->bAlpha, 255);
- }
- cyLine = MAX(iHeight, cyLine);
- pt.x += iWidth;
- cxMaxWidth = MAX(cxMaxWidth, pt.x);
- cxLine = pt.x - rc.left;
- cyMinHeight = pt.y + iHeight;
- }
- }
- else pstrNextStart = NULL;
- }
- }
- break;
- case _T('n'): // Newline
- {
- pstrText++;
- if( (uStyle & DT_SINGLELINE) != 0 ) break;
- bLineEnd = true;
- }
- break;
- case _T('p'): // Paragraph
- {
- pstrText++;
- if( pt.x > rc.left ) bLineEnd = true;
- while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
- int cyLineExtra = (int)_tcstol(pstrText, const_cast<LPTSTR*>(&pstrText), 10);
- aPIndentArray.Add((LPVOID)cyLineExtra);
- cyLine = MAX(cyLine, pTm->tmHeight + pTm->tmExternalLeading + cyLineExtra);
- }
- break;
- case _T('v'): // Vertical Align
- {
- pstrText++;
- while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
- CDuiString sVAlignStyle;
- while( *pstrText != _T('\0') && *pstrText != _T('>') && *pstrText != _T('}') ) {
- LPCTSTR pstrTemp = ::CharNext(pstrText);
- while( pstrText < pstrTemp) {
- sVAlignStyle += *pstrText++;
- }
- }
- UINT iVAlign = DT_BOTTOM;
- if (sVAlignStyle.CompareNoCase(_T("center")) == 0) iVAlign = DT_VCENTER;
- else if (sVAlignStyle.CompareNoCase(_T("top")) == 0) iVAlign = DT_TOP;
- aVAlignArray.Add((LPVOID)iVAlign);
- }
- break;
- case _T('r'): // Raw Text
- {
- pstrText++;
- bInRaw = true;
- }
- break;
- case _T('s'): // Selected text background color
- {
- pstrText++;
- bInSelected = !bInSelected;
- if( bDraw && bLineDraw ) {
- if( bInSelected ) ::SetBkMode(hDC, OPAQUE);
- else ::SetBkMode(hDC, TRANSPARENT);
- }
- }
- break;
- case _T('u'): // Underline text
- {
- pstrText++;
- TFontInfo* pFontInfo = pManager->GetFontInfo(iDefaultFont);
- if( aFontArray.GetSize() > 0 ) pFontInfo = (TFontInfo*)aFontArray.GetAt(aFontArray.GetSize() - 1);
- if( pFontInfo->bUnderline == false ) {
- HFONT hFont = pManager->GetFont(pFontInfo->sFontName, pFontInfo->iSize, pFontInfo->bBold, true, pFontInfo->bItalic);
- if( hFont == NULL ) {
- hFont = pManager->AddFont(g_iFontID, pFontInfo->sFontName, pFontInfo->iSize, pFontInfo->bBold, true, pFontInfo->bItalic);
- g_iFontID += 1;
- }
- pFontInfo = pManager->GetFontInfo(hFont);
- aFontArray.Add(pFontInfo);
- pTm = &pFontInfo->tm;
- ::SelectObject(hDC, pFontInfo->hFont);
- cyLine = MAX(cyLine, pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1));
- }
- }
- break;
- case _T('x'): // X Indent
- {
- pstrText++;
- while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
- int iWidth = (int) _tcstol(pstrText, const_cast<LPTSTR*>(&pstrText), 10);
- pt.x += iWidth;
- }
- break;
- case _T('y'): // Y Indent
- {
- pstrText++;
- while( *pstrText > _T('\0') && *pstrText <= _T(' ') ) pstrText = ::CharNext(pstrText);
- cyLine = (int) _tcstol(pstrText, const_cast<LPTSTR*>(&pstrText), 10);
- }
- break;
- }
- if( pstrNextStart != NULL ) pstrText = pstrNextStart;
- else {
- while( *pstrText != _T('\0') && *pstrText != _T('>') && *pstrText != _T('}') ) pstrText = ::CharNext(pstrText);
- pstrText = ::CharNext(pstrText);
- }
- }
- else if( !bInRaw && ( *pstrText == _T('<') || *pstrText == _T('{') ) && pstrText[1] == _T('/') )
- {
- pstrText++;
- pstrText++;
- switch( *pstrText )
- {
- case _T('c'):
- {
- pstrText++;
- aColorArray.Remove(aColorArray.GetSize() - 1);
- DWORD clrColor = dwTextColor;
- if( aColorArray.GetSize() > 0 ) clrColor = (int)aColorArray.GetAt(aColorArray.GetSize() - 1);
- ::SetTextColor(hDC, RGB(GetBValue(clrColor), GetGValue(clrColor), GetRValue(clrColor)));
- }
- break;
- case _T('p'):
- pstrText++;
- if( pt.x > rc.left ) bLineEnd = true;
- aPIndentArray.Remove(aPIndentArray.GetSize() - 1);
- cyLine = MAX(cyLine, pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1));
- break;
- case _T('v'):
- pstrText++;
- aVAlignArray.Remove(aVAlignArray.GetSize() - 1);
- break;
- case _T('s'):
- {
- pstrText++;
- bInSelected = !bInSelected;
- if( bDraw && bLineDraw ) {
- if( bInSelected ) ::SetBkMode(hDC, OPAQUE);
- else ::SetBkMode(hDC, TRANSPARENT);
- }
- }
- break;
- case _T('a'):
- {
- if( iLinkIndex < nLinkRects ) {
- if( !bLineDraw ) ::SetRect(&prcLinks[iLinkIndex], ptLinkStart.x, ptLinkStart.y, MIN(pt.x, rc.right), pt.y + pTm->tmHeight + pTm->tmExternalLeading);
- iLinkIndex++;
- }
- aColorArray.Remove(aColorArray.GetSize() - 1);
- DWORD clrColor = dwTextColor;
- if( aColorArray.GetSize() > 0 ) clrColor = (int)aColorArray.GetAt(aColorArray.GetSize() - 1);
- ::SetTextColor(hDC, RGB(GetBValue(clrColor), GetGValue(clrColor), GetRValue(clrColor)));
- bInLink = false;
- }
- case _T('b'):
- case _T('f'):
- case _T('i'):
- case _T('u'):
- {
- pstrText++;
- aFontArray.Remove(aFontArray.GetSize() - 1);
- TFontInfo* pFontInfo = (TFontInfo*)aFontArray.GetAt(aFontArray.GetSize() - 1);
- if( pFontInfo == NULL ) pFontInfo = pManager->GetFontInfo(iDefaultFont);
- if( pTm->tmItalic && pFontInfo->bItalic == false ) {
- ABC abc;
- ::GetCharABCWidths(hDC, _T(' '), _T(' '), &abc);
- pt.x += abc.abcC / 2; // 简单修正一下斜体混排的问题, 正确做法应该是http://support.microsoft.com/kb/244798/en-us
- }
- pTm = &pFontInfo->tm;
- ::SelectObject(hDC, pFontInfo->hFont);
- cyLine = MAX(cyLine, pTm->tmHeight + pTm->tmExternalLeading + (int)aPIndentArray.GetAt(aPIndentArray.GetSize() - 1));
- }
- break;
- }
- while( *pstrText != _T('\0') && *pstrText != _T('>') && *pstrText != _T('}') ) pstrText = ::CharNext(pstrText);
- pstrText = ::CharNext(pstrText);
- }
- else if( !bInRaw && *pstrText == _T('<') && pstrText[2] == _T('>') && (pstrText[1] == _T('{') || pstrText[1] == _T('}')) )
- {
- SIZE szSpace = { 0 };
- ::GetTextExtentPoint32(hDC, &pstrText[1], 1, &szSpace);
- if( bDraw && bLineDraw ) {
- iVAlign = DT_BOTTOM;
- if (aVAlignArray.GetSize() > 0) iVAlign = (UINT)aVAlignArray.GetAt(aVAlignArray.GetSize() - 1);
- if (iVAlign == DT_VCENTER) ::TextOut(hDC, pt.x + cxOffset, pt.y + (cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading)/2, &pstrText[1], 1);
- else if (iVAlign == DT_TOP) ::TextOut(hDC, pt.x + cxOffset, pt.y, &pstrText[1], 1);
- else ::TextOut(hDC, pt.x + cxOffset, pt.y + cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading, &pstrText[1], 1);
- }
- pt.x += szSpace.cx;
- cxMaxWidth = MAX(cxMaxWidth, pt.x);
- cxLine = pt.x - rc.left;
- pstrText++;pstrText++;pstrText++;
- }
- else if( !bInRaw && *pstrText == _T('{') && pstrText[2] == _T('}') && (pstrText[1] == _T('<') || pstrText[1] == _T('>')) )
- {
- SIZE szSpace = { 0 };
- ::GetTextExtentPoint32(hDC, &pstrText[1], 1, &szSpace);
- if( bDraw && bLineDraw ) {
- iVAlign = DT_BOTTOM;
- if (aVAlignArray.GetSize() > 0) iVAlign = (UINT)aVAlignArray.GetAt(aVAlignArray.GetSize() - 1);
- if (iVAlign == DT_VCENTER) ::TextOut(hDC, pt.x + cxOffset, pt.y + (cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading)/2, &pstrText[1], 1);
- else if (iVAlign == DT_TOP) ::TextOut(hDC, pt.x + cxOffset, pt.y, &pstrText[1], 1);
- else ::TextOut(hDC, pt.x + cxOffset, pt.y + cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading, &pstrText[1], 1);
- }
- pt.x += szSpace.cx;
- cxMaxWidth = MAX(cxMaxWidth, pt.x);
- cxLine = pt.x - rc.left;
- pstrText++;pstrText++;pstrText++;
- }
- else if( !bInRaw && *pstrText == _T(' ') )
- {
- SIZE szSpace = { 0 };
- ::GetTextExtentPoint32(hDC, _T(" "), 1, &szSpace);
- // Still need to paint the space because the font might have
- // underline formatting.
- if( bDraw && bLineDraw ) {
- iVAlign = DT_BOTTOM;
- if (aVAlignArray.GetSize() > 0) iVAlign = (UINT)aVAlignArray.GetAt(aVAlignArray.GetSize() - 1);
- if (iVAlign == DT_VCENTER) ::TextOut(hDC, pt.x + cxOffset, pt.y + (cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading)/2, _T(" "), 1);
- else if (iVAlign == DT_TOP) ::TextOut(hDC, pt.x + cxOffset, pt.y, _T(" "), 1);
- else ::TextOut(hDC, pt.x + cxOffset, pt.y + cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading, _T(" "), 1);
- }
- pt.x += szSpace.cx;
- cxMaxWidth = MAX(cxMaxWidth, pt.x);
- cxLine = pt.x - rc.left;
- pstrText++;
- }
- else
- {
- int cchChars = 0;
- int cchSize = 0;
- int cchLastGoodWord = 0;
- int cchLastGoodSize = 0;
- LPCTSTR p = pstrText;
- LPCTSTR pstrNext;
- SIZE szText = { 0 };
- if( !bInRaw && *p == _T('<') || *p == _T('{') ) p++, cchChars++, cchSize++;
- while( *p != _T('\0') && *p != _T('\n') ) {
- // This part makes sure that we're word-wrapping if needed or providing support
- // for DT_END_ELLIPSIS. Unfortunately the GetTextExtentPoint32() call is pretty
- // slow when repeated so often.
- // TODO: Rewrite and use GetTextExtentExPoint() instead!
- if( bInRaw ) {
- if( ( *p == _T('<') || *p == _T('{') ) && p[1] == _T('/')
- && p[2] == _T('r') && ( p[3] == _T('>') || p[3] == _T('}') ) ) {
- p += 4;
- bInRaw = false;
- break;
- }
- }
- else {
- if( *p == _T('<') || *p == _T('{') ) break;
- }
- pstrNext = ::CharNext(p);
- cchChars++;
- cchSize += (int)(pstrNext - p);
- szText.cx = cchChars * pTm->tmMaxCharWidth;
- if( pt.x + szText.cx >= rc.right ) {
- ::GetTextExtentPoint32(hDC, pstrText, cchSize, &szText);
- }
- if( pt.x + szText.cx > rc.right ) {
- if( pt.x + szText.cx > rc.right && cchChars > 1) {
- cchChars--;
- cchSize -= (int)(pstrNext - p);
- }
- if( (uStyle & DT_WORDBREAK) != 0 && cchLastGoodWord > 0 ) {
- cchChars = cchLastGoodWord;
- cchSize = cchLastGoodSize;
- }
- if( (uStyle & DT_END_ELLIPSIS) != 0 && cchChars > 0 ) {
- cchChars -= 1;
- LPCTSTR pstrPrev = ::CharPrev(pstrText, p);
- if( cchChars > 0 ) {
- cchChars -= 1;
- pstrPrev = ::CharPrev(pstrText, pstrPrev);
- cchSize -= (int)(p - pstrPrev);
- }
- else
- cchSize -= (int)(p - pstrPrev);
- pt.x = rc.right;
- }
- bLineEnd = true;
- cxMaxWidth = MAX(cxMaxWidth, pt.x);
- cxLine = pt.x - rc.left;
- break;
- }
- if (!( ( p[0] >= _T('a') && p[0] <= _T('z') ) || ( p[0] >= _T('A') && p[0] <= _T('Z') ) )) {
- cchLastGoodWord = cchChars;
- cchLastGoodSize = cchSize;
- }
- if( *p == _T(' ') ) {
- cchLastGoodWord = cchChars;
- cchLastGoodSize = cchSize;
- }
- p = ::CharNext(p);
- }
-
- ::GetTextExtentPoint32(hDC, pstrText, cchSize, &szText);
- if( bDraw && bLineDraw ) {
- iVAlign = DT_BOTTOM;
- if (aVAlignArray.GetSize() > 0) iVAlign = (UINT)aVAlignArray.GetAt(aVAlignArray.GetSize() - 1);
- if (iVAlign == DT_VCENTER) ::TextOut(hDC, pt.x + cxOffset, pt.y + (cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading)/2, pstrText, cchSize);
- else if (iVAlign == DT_TOP) ::TextOut(hDC, pt.x + cxOffset, pt.y, pstrText, cchSize);
- else ::TextOut(hDC, pt.x + cxOffset, pt.y + cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading, pstrText, cchSize);
- if( pt.x >= rc.right && (uStyle & DT_END_ELLIPSIS) != 0 ) {
- if (iVAlign == DT_VCENTER) ::TextOut(hDC, pt.x + cxOffset + szText.cx, pt.y + (cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading)/2, _T("..."), 3);
- else if (iVAlign == DT_TOP) ::TextOut(hDC, pt.x + cxOffset + szText.cx, pt.y, _T("..."), 3);
- else ::TextOut(hDC, pt.x + cxOffset + szText.cx, pt.y + cyLineHeight - pTm->tmHeight - pTm->tmExternalLeading, _T("..."), 3);
- }
- }
- pt.x += szText.cx;
- cxMaxWidth = MAX(cxMaxWidth, pt.x);
- cxLine = pt.x - rc.left;
- pstrText += cchSize;
- }
- if( pt.x >= rc.right || *pstrText == _T('\n') || *pstrText == _T('\0') ) bLineEnd = true;
- if( bDraw && bLineEnd ) {
- if( !bLineDraw ) {
- aFontArray.Resize(aLineFontArray.GetSize());
- ::CopyMemory(aFontArray.GetData(), aLineFontArray.GetData(), aLineFontArray.GetSize() * sizeof(LPVOID));
- aColorArray.Resize(aLineColorArray.GetSize());
- ::CopyMemory(aColorArray.GetData(), aLineColorArray.GetData(), aLineColorArray.GetSize() * sizeof(LPVOID));
- aPIndentArray.Resize(aLinePIndentArray.GetSize());
- ::CopyMemory(aPIndentArray.GetData(), aLinePIndentArray.GetData(), aLinePIndentArray.GetSize() * sizeof(LPVOID));
- aVAlignArray.Resize(aLineVAlignArray.GetSize());
- ::CopyMemory(aVAlignArray.GetData(), aLineVAlignArray.GetData(), aLineVAlignArray.GetSize() * sizeof(LPVOID));
- cxLineWidth = cxLine;
- cyLineHeight = cyLine;
- pstrText = pstrLineBegin;
- bInRaw = bLineInRaw;
- bInSelected = bLineInSelected;
- DWORD clrColor = dwTextColor;
- if( aColorArray.GetSize() > 0 ) clrColor = (int)aColorArray.GetAt(aColorArray.GetSize() - 1);
- ::SetTextColor(hDC, RGB(GetBValue(clrColor), GetGValue(clrColor), GetRValue(clrColor)));
- TFontInfo* pFontInfo = (TFontInfo*)aFontArray.GetAt(aFontArray.GetSize() - 1);
- if( pFontInfo == NULL ) pFontInfo = pManager->GetFontInfo(iDefaultFont);
- pTm = &pFontInfo->tm;
- ::SelectObject(hDC, pFontInfo->hFont);
- if( bInSelected ) ::SetBkMode(hDC, OPAQUE);
- }
- else {
- aLineFontArray.Resize(aFontArray.GetSize());
- ::CopyMemory(aLineFontArray.GetData(), aFontArray.GetData(), aFontArray.GetSize() * sizeof(LPVOID));
- aLineColorArray.Resize(aColorArray.GetSize());
- ::CopyMemory(aLineColorArray.GetData(), aColorArray.GetData(), aColorArray.GetSize() * sizeof(LPVOID));
- aLinePIndentArray.Resize(aPIndentArray.GetSize());
- ::CopyMemory(aLinePIndentArray.GetData(), aPIndentArray.GetData(), aPIndentArray.GetSize() * sizeof(LPVOID));
- aLineVAlignArray.Resize(aVAlignArray.GetSize());
- ::CopyMemory(aLineVAlignArray.GetData(), aVAlignArray.GetData(), aVAlignArray.GetSize() * sizeof(LPVOID));
- pstrLineBegin = pstrText;
- bLineInSelected = bInSelected;
- bLineInRaw = bInRaw;
- }
- }
- ASSERT(iLinkIndex<=nLinkRects);
- }
- nLinkRects = iLinkIndex;
- // Return size of text when requested
- if( (uStyle & DT_CALCRECT) != 0 ) {
- rc.bottom = MAX(cyMinHeight, pt.y + cyLine);
- rc.right = MIN(rc.right, cxMaxWidth);
- }
- if( bDraw ) ::SelectClipRgn(hDC, hOldRgn);
- ::DeleteObject(hOldRgn);
- ::DeleteObject(hRgn);
- ::SelectObject(hDC, hOldFont);
- }
- HBITMAP CRenderEngine::GenerateBitmap(CPaintManagerUI* pManager, RECT rc, CControlUI* pStopControl, DWORD dwFilterColor)
- {
- if (pManager == NULL) return NULL;
- int cx = rc.right - rc.left;
- int cy = rc.bottom - rc.top;
- bool bUseOffscreenBitmap = true;
- HDC hPaintDC = ::CreateCompatibleDC(pManager->GetPaintDC());
- ASSERT(hPaintDC);
- HBITMAP hPaintBitmap = NULL;
- if (pStopControl == NULL && !pManager->IsLayered()) hPaintBitmap = pManager->GetPaintOffscreenBitmap();
- if( hPaintBitmap == NULL ) {
- bUseOffscreenBitmap = false;
- hPaintBitmap = ::CreateCompatibleBitmap(pManager->GetPaintDC(), rc.right, rc.bottom);
- ASSERT(hPaintBitmap);
- }
- HBITMAP hOldPaintBitmap = (HBITMAP) ::SelectObject(hPaintDC, hPaintBitmap);
- if (!bUseOffscreenBitmap) {
- CControlUI* pRoot = pManager->GetRoot();
- pRoot->Paint(hPaintDC, rc, pStopControl);
- }
- BITMAPINFO bmi = { 0 };
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = cx;
- bmi.bmiHeader.biHeight = cy;
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
- bmi.bmiHeader.biSizeImage = cx * cy * sizeof(DWORD);
- LPDWORD pDest = NULL;
- HDC hCloneDC = ::CreateCompatibleDC(pManager->GetPaintDC());
- HBITMAP hBitmap = ::CreateDIBSection(pManager->GetPaintDC(), &bmi, DIB_RGB_COLORS, (LPVOID*) &pDest, NULL, 0);
- ASSERT(hCloneDC);
- ASSERT(hBitmap);
- if( hBitmap != NULL )
- {
- HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(hCloneDC, hBitmap);
- ::BitBlt(hCloneDC, 0, 0, cx, cy, hPaintDC, rc.left, rc.top, SRCCOPY);
- RECT rcClone = {0, 0, cx, cy};
- if (dwFilterColor > 0x00FFFFFF) DrawColor(hCloneDC, rcClone, dwFilterColor);
- ::SelectObject(hCloneDC, hOldBitmap);
- ::DeleteDC(hCloneDC);
- ::GdiFlush();
- }
- // Cleanup
- ::SelectObject(hPaintDC, hOldPaintBitmap);
- if (!bUseOffscreenBitmap) ::DeleteObject(hPaintBitmap);
- ::DeleteDC(hPaintDC);
- return hBitmap;
- }
- HBITMAP CRenderEngine::GenerateBitmap(CPaintManagerUI* pManager, CControlUI* pControl, RECT rc, DWORD dwFilterColor)
- {
- if (pManager == NULL || pControl == NULL) return NULL;
- int cx = rc.right - rc.left;
- int cy = rc.bottom - rc.top;
- HDC hPaintDC = ::CreateCompatibleDC(pManager->GetPaintDC());
- HBITMAP hPaintBitmap = ::CreateCompatibleBitmap(pManager->GetPaintDC(), rc.right, rc.bottom);
- ASSERT(hPaintDC);
- ASSERT(hPaintBitmap);
- HBITMAP hOldPaintBitmap = (HBITMAP) ::SelectObject(hPaintDC, hPaintBitmap);
- pControl->Paint(hPaintDC, rc, NULL);
- BITMAPINFO bmi = { 0 };
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = cx;
- bmi.bmiHeader.biHeight = cy;
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
- bmi.bmiHeader.biSizeImage = cx * cy * sizeof(DWORD);
- LPDWORD pDest = NULL;
- HDC hCloneDC = ::CreateCompatibleDC(pManager->GetPaintDC());
- HBITMAP hBitmap = ::CreateDIBSection(pManager->GetPaintDC(), &bmi, DIB_RGB_COLORS, (LPVOID*) &pDest, NULL, 0);
- ASSERT(hCloneDC);
- ASSERT(hBitmap);
- if( hBitmap != NULL )
- {
- HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(hCloneDC, hBitmap);
- ::BitBlt(hCloneDC, 0, 0, cx, cy, hPaintDC, rc.left, rc.top, SRCCOPY);
- RECT rcClone = {0, 0, cx, cy};
- if (dwFilterColor > 0x00FFFFFF) DrawColor(hCloneDC, rcClone, dwFilterColor);
- ::SelectObject(hCloneDC, hOldBitmap);
- ::DeleteDC(hCloneDC);
- ::GdiFlush();
- }
- // Cleanup
- ::SelectObject(hPaintDC, hOldPaintBitmap);
- ::DeleteObject(hPaintBitmap);
- ::DeleteDC(hPaintDC);
- return hBitmap;
- }
- SIZE CRenderEngine::GetTextSize( HDC hDC, CPaintManagerUI* pManager , LPCTSTR pstrText, int iFont, UINT uStyle )
- {
- CDuiString sText = pstrText;
- CPaintManagerUI::ProcessMultiLanguageTokens(sText);
- pstrText = sText;
- SIZE size = {0,0};
- ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
- if( pstrText == NULL || pManager == NULL ) return size;
- ::SetBkMode(hDC, TRANSPARENT);
- HFONT hOldFont = (HFONT)::SelectObject(hDC, pManager->GetFont(iFont));
- GetTextExtentPoint32(hDC, pstrText, _tcslen(pstrText) , &size);
- ::SelectObject(hDC, hOldFont);
- return size;
- }
- } // namespace DuiLib
|