1 // xImaWnd.cpp : Windows functions
\r
2 /* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
\r
3 * CxImage version 6.0.0 02/Feb/2008
\r
8 #include "ximaiter.h"
\r
11 ////////////////////////////////////////////////////////////////////////////////
\r
12 #if defined (_WIN32_WCE)
\r
14 #ifndef DEFAULT_GUI_FONT
\r
15 #define DEFAULT_GUI_FONT 17
\r
18 #ifndef PROOF_QUALITY
\r
19 #define PROOF_QUALITY 2
\r
22 struct DIBINFO : public BITMAPINFO
\r
24 RGBQUAD arColors[255]; // Color table info - adds an extra 255 entries to palette
\r
25 operator LPBITMAPINFO() { return (LPBITMAPINFO) this; }
\r
26 operator LPBITMAPINFOHEADER() { return &bmiHeader; }
\r
27 RGBQUAD* ColorTable() { return bmiColors; }
\r
30 int BytesPerLine(int nWidth, int nBitsPerPixel)
\r
32 return ( (nWidth * nBitsPerPixel + 31) & (~31) ) / 8;
\r
35 int NumColorEntries(int nBitsPerPixel, int nCompression, DWORD biClrUsed)
\r
38 switch (nBitsPerPixel)
\r
43 nColors = 4; break; // winCE only
\r
45 nColors = 16; break;
\r
47 nColors =256; break;
\r
52 nColors = 3; break; // I've found that PocketPCs need this regardless of BI_RGB or BI_BITFIELDS
\r
56 // If biClrUsed is provided, and it is a legal value, use it
\r
57 if (biClrUsed > 0 && biClrUsed <= (DWORD)nColors)
\r
64 HDC hdc, // handle to DC
\r
65 HBITMAP hbmp, // handle to bitmap
\r
66 UINT uStartScan, // first scan line to set
\r
67 UINT cScanLines, // number of scan lines to copy
\r
68 LPVOID lpvBits, // array for bitmap bits
\r
69 LPBITMAPINFO lpbi, // bitmap data buffer
\r
70 UINT uUsage // RGB or palette index
\r
73 UINT iColorTableSize = 0;
\r
78 // Get dimensions of bitmap
\r
80 if (!::GetObject(hbmp, sizeof(bm),(LPVOID)&bm))
\r
83 //3. Creating new bitmap and receive pointer to it's bits.
\r
84 HBITMAP hTargetBitmap;
\r
87 //3.1 Initilize DIBINFO structure
\r
89 dibInfo.bmiHeader.biBitCount = 24;
\r
90 dibInfo.bmiHeader.biClrImportant = 0;
\r
91 dibInfo.bmiHeader.biClrUsed = 0;
\r
92 dibInfo.bmiHeader.biCompression = 0;
\r
93 dibInfo.bmiHeader.biHeight = bm.bmHeight;
\r
94 dibInfo.bmiHeader.biPlanes = 1;
\r
95 dibInfo.bmiHeader.biSize = 40;
\r
96 dibInfo.bmiHeader.biSizeImage = bm.bmHeight*BytesPerLine(bm.bmWidth,24);
\r
97 dibInfo.bmiHeader.biWidth = bm.bmWidth;
\r
98 dibInfo.bmiHeader.biXPelsPerMeter = 3780;
\r
99 dibInfo.bmiHeader.biYPelsPerMeter = 3780;
\r
100 dibInfo.bmiColors[0].rgbBlue = 0;
\r
101 dibInfo.bmiColors[0].rgbGreen = 0;
\r
102 dibInfo.bmiColors[0].rgbRed = 0;
\r
103 dibInfo.bmiColors[0].rgbReserved = 0;
\r
105 //3.2 Create bitmap and receive pointer to points into pBuffer
\r
106 HDC hDC = ::GetDC(NULL);
\r
108 hTargetBitmap = CreateDIBSection(
\r
110 (const BITMAPINFO*)dibInfo,
\r
116 ::ReleaseDC(NULL, hDC);
\r
118 //4. Copy source bitmap into the target bitmap.
\r
120 //4.1 Create 2 device contexts
\r
121 HDC memDc = CreateCompatibleDC(NULL);
\r
126 HDC targetDc = CreateCompatibleDC(NULL);
\r
131 //4.2 Select source bitmap into one DC, target into another
\r
132 HBITMAP hOldBitmap1 = (HBITMAP)::SelectObject(memDc, hbmp);
\r
133 HBITMAP hOldBitmap2 = (HBITMAP)::SelectObject(targetDc, hTargetBitmap);
\r
135 //4.3 Copy source bitmap into the target one
\r
136 BitBlt(targetDc, 0, 0, bm.bmWidth, bm.bmHeight, memDc, 0, 0, SRCCOPY);
\r
138 //4.4 Restore device contexts
\r
139 ::SelectObject(memDc, hOldBitmap1);
\r
140 ::SelectObject(targetDc, hOldBitmap2);
\r
142 DeleteDC(targetDc);
\r
144 //Here we can bitmap bits: pBuffer. Note:
\r
145 // 1. pBuffer contains 3 bytes per point
\r
146 // 2. Lines ane from the bottom to the top!
\r
147 // 3. Points in the line are from the left to the right
\r
148 // 4. Bytes in one point are BGR (blue, green, red) not RGB
\r
149 // 5. Don't delete pBuffer, it will be automatically deleted
\r
150 // when delete hTargetBitmap
\r
153 DeleteObject(hbmp);
\r
154 //DeleteObject(hTargetBitmap);
\r
160 ////////////////////////////////////////////////////////////////////////////////
\r
161 #if CXIMAGE_SUPPORT_WINDOWS
\r
162 ////////////////////////////////////////////////////////////////////////////////
\r
163 long CxImage::Blt(HDC pDC, long x, long y)
\r
165 if((pDib==0)||(pDC==0)||(!info.bEnabled)) return 0;
\r
167 HBRUSH brImage = CreateDIBPatternBrushPt(pDib, DIB_RGB_COLORS);
\r
169 SetBrushOrgEx(pDC,x,y,&pt); //<RT>
\r
170 HBRUSH brOld = (HBRUSH) SelectObject(pDC, brImage);
\r
171 PatBlt(pDC, x, y, head.biWidth, head.biHeight, PATCOPY);
\r
172 SelectObject(pDC, brOld);
\r
173 SetBrushOrgEx(pDC,pt.x,pt.y,NULL);
\r
174 DeleteObject(brImage);
\r
177 ////////////////////////////////////////////////////////////////////////////////
\r
179 * Transfer the image in a global bitmap handle (clipboard copy)
\r
181 HANDLE CxImage::CopyToHandle()
\r
185 hMem= GlobalAlloc(GHND, GetSize());
\r
187 BYTE* pDst=(BYTE*)GlobalLock(hMem);
\r
189 memcpy(pDst,pDib,GetSize());
\r
191 GlobalUnlock(hMem);
\r
196 ////////////////////////////////////////////////////////////////////////////////
\r
198 * Global object (clipboard paste) constructor
\r
199 * \param hMem: source bitmap object, the clipboard format must be CF_DIB
\r
200 * \return true if everything is ok
\r
202 bool CxImage::CreateFromHANDLE(HANDLE hMem)
\r
207 DWORD dwSize = GlobalSize(hMem);
\r
208 if (!dwSize) return false;
\r
210 BYTE *lpVoid; //pointer to the bitmap
\r
211 lpVoid = (BYTE *)GlobalLock(hMem);
\r
212 BITMAPINFOHEADER *pHead; //pointer to the bitmap header
\r
213 pHead = (BITMAPINFOHEADER *)lpVoid;
\r
216 //CxMemFile hFile(lpVoid,dwSize);
\r
218 //copy the bitmap header
\r
219 memcpy(&head,pHead,sizeof(BITMAPINFOHEADER));
\r
220 //check if it's a top-down bitmap
\r
221 bool bTopDownDib = head.biHeight<0;
\r
222 if (bTopDownDib) head.biHeight=-head.biHeight;
\r
224 if(!Create(head.biWidth,head.biHeight,head.biBitCount)){
\r
225 GlobalUnlock(lpVoid);
\r
229 SetXDPI((long)floor(head.biXPelsPerMeter * 254.0 / 10000.0 + 0.5));
\r
230 SetYDPI((long)floor(head.biYPelsPerMeter * 254.0 / 10000.0 + 0.5));
\r
232 /*//copy the pixels (old way)
\r
233 if((pHead->biCompression != BI_RGB) || (pHead->biBitCount == 32)){ //<Jรถrgen Alfredsson>
\r
235 // set the internal header in the dib
\r
236 memcpy(pDib,&head,sizeof(head));
\r
237 // get the bitfield masks
\r
239 memcpy(bf,lpVoid+pHead->biSize,12);
\r
240 // transform into RGB
\r
241 Bitfield2RGB(lpVoid+pHead->biSize+12,bf[0],bf[1],bf[2],(BYTE)pHead->biBitCount);
\r
242 } else { //normal bitmap
\r
243 memcpy(pDib,lpVoid,GetSize());
\r
246 // <Michael Gandyra>
\r
247 // fill in color map
\r
248 bool bIsOldBmp = (head.biSize == sizeof(BITMAPCOREHEADER));
\r
249 RGBQUAD *pRgb = GetPalette();
\r
251 // number of colors to fill in
\r
252 int nColors = DibNumColors(pHead);
\r
254 /* get pointer to BITMAPCOREINFO (old style 1.x) */
\r
255 LPBITMAPCOREINFO lpbmc = (LPBITMAPCOREINFO)lpVoid;
\r
256 for (int i = nColors - 1; i >= 0; i--) {
\r
257 pRgb[i].rgbRed = lpbmc->bmciColors[i].rgbtRed;
\r
258 pRgb[i].rgbGreen = lpbmc->bmciColors[i].rgbtGreen;
\r
259 pRgb[i].rgbBlue = lpbmc->bmciColors[i].rgbtBlue;
\r
260 pRgb[i].rgbReserved = (BYTE)0;
\r
263 /* get pointer to BITMAPINFO (new style 3.x) */
\r
264 LPBITMAPINFO lpbmi = (LPBITMAPINFO)lpVoid;
\r
265 for (int i = nColors - 1; i >= 0; i--) {
\r
266 pRgb[i].rgbRed = lpbmi->bmiColors[i].rgbRed;
\r
267 pRgb[i].rgbGreen = lpbmi->bmiColors[i].rgbGreen;
\r
268 pRgb[i].rgbBlue = lpbmi->bmiColors[i].rgbBlue;
\r
269 pRgb[i].rgbReserved = (BYTE)0;
\r
274 // <Michael Gandyra>
\r
275 DWORD dwCompression = pHead->biCompression;
\r
276 // compressed bitmap ?
\r
277 if(dwCompression!=BI_RGB || pHead->biBitCount==32 || pHead->biBitCount ==16) {
\r
278 // get the bitmap bits
\r
279 LPSTR lpDIBBits = (LPSTR)((BYTE*)pHead + *(DWORD*)pHead + (WORD)(GetNumColors() * sizeof(RGBQUAD)));
\r
280 // decode and copy them to our image
\r
281 switch (pHead->biBitCount) {
\r
285 if (dwCompression == BI_BITFIELDS || dwCompression == BI_RGB) {
\r
286 // get the bitfield masks
\r
288 memcpy(bf,lpVoid+pHead->biSize,12);
\r
289 // transform into RGB
\r
290 Bitfield2RGB(lpVoid+pHead->biSize+12,bf[0],bf[1],bf[2],(BYTE)pHead->biBitCount);
\r
292 // "unknown compression";
\r
293 GlobalUnlock(lpVoid);
\r
300 // get the bitfield masks
\r
303 if (dwCompression == BI_BITFIELDS) {
\r
304 memcpy(bf,lpVoid+pHead->biSize,12);
\r
309 bf[2] = 0x1F; // RGB555
\r
312 memcpy(info.pImage, lpDIBBits + offset, head.biHeight*((head.biWidth+1)/2)*4);
\r
313 // transform into RGB
\r
314 Bitfield2RGB(info.pImage, bf[0], bf[1], bf[2], 16);
\r
321 switch (dwCompression) {
\r
324 BYTE status_byte = 0;
\r
325 BYTE second_byte = 0;
\r
328 BOOL low_nibble = FALSE;
\r
329 CImageIterator iter(this);
\r
331 for (BOOL bContinue = TRUE; bContinue; ) {
\r
332 status_byte = *(lpDIBBits++);
\r
333 switch (status_byte) {
\r
335 status_byte = *(lpDIBBits++);
\r
336 switch (status_byte) {
\r
337 case RLE_ENDOFLINE :
\r
340 low_nibble = FALSE;
\r
342 case RLE_ENDOFBITMAP :
\r
347 // read the delta values
\r
350 delta_x = *(lpDIBBits++);
\r
351 delta_y = *(lpDIBBits++);
\r
353 bits += delta_x / 2;
\r
354 scanline += delta_y;
\r
358 second_byte = *(lpDIBBits++);
\r
359 BYTE* sline = iter.GetRow(scanline);
\r
360 for (int i = 0; i < status_byte; i++) {
\r
361 if ((BYTE*)(sline+bits) < (BYTE*)(info.pImage+head.biSizeImage)){
\r
364 *(sline + bits) |= (second_byte & 0x0f);
\r
366 *(sline + bits) |= (second_byte & 0xf0)>>4;
\r
370 *(sline + bits) = (BYTE)(second_byte & 0x0f)<<4;
\r
372 *(sline + bits) = (BYTE)(second_byte & 0xf0);
\r
376 if ((i & 1) && (i != (status_byte - 1)))
\r
377 second_byte = *(lpDIBBits++);
\r
379 low_nibble = !low_nibble;
\r
381 if ((((status_byte+1) >> 1) & 1 ) == 1)
\r
382 second_byte = *(lpDIBBits++);
\r
388 BYTE* sline = iter.GetRow(scanline);
\r
389 second_byte = *(lpDIBBits++);
\r
390 for (unsigned i = 0; i < status_byte; i++) {
\r
391 if ((BYTE*)(sline+bits) < (BYTE*)(info.pImage+head.biSizeImage)){
\r
394 *(sline + bits) |= (second_byte & 0x0f);
\r
396 *(sline + bits) |= (second_byte & 0xf0)>>4;
\r
400 *(sline + bits) = (BYTE)(second_byte & 0x0f)<<4;
\r
402 *(sline + bits) = (BYTE)(second_byte & 0xf0);
\r
405 low_nibble = !low_nibble;
\r
415 BYTE status_byte = 0;
\r
416 BYTE second_byte = 0;
\r
419 CImageIterator iter(this);
\r
421 for (BOOL bContinue = TRUE; bContinue; ) {
\r
422 status_byte = *(lpDIBBits++);
\r
423 if (status_byte==RLE_COMMAND) {
\r
424 status_byte = *(lpDIBBits++);
\r
425 switch (status_byte) {
\r
426 case RLE_ENDOFLINE :
\r
430 case RLE_ENDOFBITMAP :
\r
435 // read the delta values
\r
438 delta_x = *(lpDIBBits++);
\r
439 delta_y = *(lpDIBBits++);
\r
442 scanline += delta_y;
\r
446 int nNumBytes = sizeof(BYTE) * status_byte;
\r
447 memcpy((void *)(iter.GetRow(scanline) + bits), lpDIBBits, nNumBytes);
\r
448 lpDIBBits += nNumBytes;
\r
449 // align run length to even number of bytes
\r
450 if ((status_byte & 1) == 1)
\r
451 second_byte = *(lpDIBBits++);
\r
452 bits += status_byte;
\r
456 BYTE *sline = iter.GetRow(scanline);
\r
457 second_byte = *(lpDIBBits++);
\r
458 for (unsigned i = 0; i < status_byte; i++) {
\r
459 if ((DWORD)bits<info.dwEffWidth){
\r
460 *(sline + bits) = second_byte;
\r
463 bContinue = FALSE; //don't delete: we are in memory, it is not as with files
\r
473 // "compression type not supported";
\r
474 GlobalUnlock(lpVoid);
\r
481 //normal bitmap (not compressed)
\r
482 memcpy(pDib,lpVoid,GetSize());
\r
485 GlobalUnlock(lpVoid);
\r
487 if (bTopDownDib) Flip();
\r
493 ////////////////////////////////////////////////////////////////////////////////
\r
495 * Transfer the image in a bitmap handle
\r
496 * \param hdc: target device context (the screen, usually)
\r
497 * \return bitmap handle, or NULL if an error occurs.
\r
499 HBITMAP CxImage::MakeBitmap(HDC hdc)
\r
505 // this call to CreateBitmap doesn't create a DIB <jaslet>
\r
506 // // Create a device-independent bitmap <CSC>
\r
507 // return CreateBitmap(head.biWidth,head.biHeight, 1, head.biBitCount, GetBits());
\r
508 // use instead this code
\r
509 HDC hMemDC = CreateCompatibleDC(NULL);
\r
511 HBITMAP bmp = CreateDIBSection(hMemDC,(LPBITMAPINFO)pDib,DIB_RGB_COLORS, &pBit32, NULL, 0);
\r
512 if (pBit32) memcpy(pBit32, GetBits(), head.biSizeImage);
\r
517 // this single line seems to work very well
\r
518 //HBITMAP bmp = CreateDIBitmap(hdc, (LPBITMAPINFOHEADER)pDib, CBM_INIT,
\r
519 // GetBits(), (LPBITMAPINFO)pDib, DIB_RGB_COLORS);
\r
520 // this alternative works also with _WIN32_WCE
\r
522 HBITMAP bmp = CreateDIBSection(hdc, (LPBITMAPINFO)pDib, DIB_RGB_COLORS, &pBit32, NULL, 0);
\r
523 if (pBit32) memcpy(pBit32, GetBits(), head.biSizeImage);
\r
527 ////////////////////////////////////////////////////////////////////////////////
\r
529 * Bitmap resource constructor
\r
530 * \param hbmp : bitmap resource handle
\r
531 * \param hpal : (optional) palette, useful for 8bpp DC
\r
532 * \return true if everything is ok
\r
534 bool CxImage::CreateFromHBITMAP(HBITMAP hbmp, HPALETTE hpal)
\r
541 // get informations about the bitmap
\r
542 GetObject(hbmp, sizeof(BITMAP), (LPSTR) &bm);
\r
543 // create the image
\r
544 if (!Create(bm.bmWidth, bm.bmHeight, bm.bmBitsPixel, 0))
\r
546 // create a device context for the bitmap
\r
547 HDC dc = ::GetDC(NULL);
\r
552 SelectObject(dc,hpal); //the palette you should get from the user or have a stock one
\r
553 RealizePalette(dc);
\r
557 if (GetDIBits(dc, hbmp, 0, head.biHeight, info.pImage,
\r
558 (LPBITMAPINFO)pDib, DIB_RGB_COLORS) == 0){ //replace &head with pDib <Wil Stark>
\r
559 strcpy(info.szLastError,"GetDIBits failed");
\r
560 ::ReleaseDC(NULL, dc);
\r
563 ::ReleaseDC(NULL, dc);
\r
568 ////////////////////////////////////////////////////////////////////////////////
\r
570 * icon resource constructor
\r
571 * \param hico : icon resource handle
\r
572 * \return true if everything is ok
\r
573 * \author []; changes [Arlen Albert Keshabian]
\r
575 #if !defined (_WIN32_WCE)
\r
576 bool CxImage::CreateFromHICON(HICON hico)
\r
578 if (!Destroy() || !hico)
\r
581 bool l_bResult = true;
\r
584 GetIconInfo(hico,&iinfo);
\r
587 GetObject(iinfo.hbmColor, sizeof(BITMAP), &l_Bitmap);
\r
589 if(l_Bitmap.bmBitsPixel == 32)
\r
591 BITMAPINFO l_BitmapInfo;
\r
592 l_BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
\r
593 l_BitmapInfo.bmiHeader.biWidth = l_Bitmap.bmWidth;
\r
594 l_BitmapInfo.bmiHeader.biHeight = l_Bitmap.bmHeight;
\r
595 l_BitmapInfo.bmiHeader.biPlanes = l_Bitmap.bmPlanes;
\r
596 l_BitmapInfo.bmiHeader.biBitCount = l_Bitmap.bmBitsPixel;
\r
597 l_BitmapInfo.bmiHeader.biCompression = BI_RGB;
\r
599 RGBQUAD *l_pRawBytes = new RGBQUAD[l_Bitmap.bmWidth * l_Bitmap.bmHeight];
\r
601 HDC dc = ::GetDC(NULL);
\r
605 if(GetDIBits(dc, iinfo.hbmColor, 0, l_Bitmap.bmHeight, l_pRawBytes, &l_BitmapInfo, DIB_RGB_COLORS))
\r
606 l_bResult = CreateFromArray((BYTE*)l_pRawBytes, l_Bitmap.bmWidth, l_Bitmap.bmHeight, l_Bitmap.bmBitsPixel, l_Bitmap.bmWidthBytes, false);
\r
610 ::ReleaseDC(NULL, dc);
\r
615 delete [] l_pRawBytes;
\r
619 l_bResult = CreateFromHBITMAP(iinfo.hbmColor);
\r
620 #if CXIMAGE_SUPPORT_ALPHA
\r
624 mask.CreateFromHBITMAP(iinfo.hbmMask);
\r
632 DeleteObject(iinfo.hbmColor); //<Sims>
\r
633 DeleteObject(iinfo.hbmMask); //<Sims>
\r
637 #endif //_WIN32_WCE
\r
638 ////////////////////////////////////////////////////////////////////////////////
\r
639 long CxImage::Draw(HDC hdc, const RECT& rect, RECT* pClipRect, bool bSmooth)
\r
641 return Draw(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pClipRect,bSmooth);
\r
643 ////////////////////////////////////////////////////////////////////////////////
\r
645 * Draws the image in the specified device context, with support for alpha channel, alpha palette, transparency, opacity.
\r
646 * \param hdc : destination device context
\r
647 * \param x,y : (optional) offset
\r
648 * \param cx,cy : (optional) size.
\r
649 * - If cx or cy are not specified (or less than 0), the normal width or height will be used
\r
650 * - If cx or cy are different than width or height, the image will be stretched
\r
652 * \param pClipRect : limit the drawing operations inside a given rectangle in the output device context.
\r
653 * \param bSmooth : activates a bilinear filter that will enhance the appearence for zommed pictures.
\r
654 * Quite slow. Needs CXIMAGE_SUPPORT_INTERPOLATION.
\r
655 * \return true if everything is ok
\r
657 long CxImage::Draw(HDC hdc, long x, long y, long cx, long cy, RECT* pClipRect, bool bSmooth)
\r
659 if((pDib==0)||(hdc==0)||(cx==0)||(cy==0)||(!info.bEnabled)) return 0;
\r
661 if (cx < 0) cx = head.biWidth;
\r
662 if (cy < 0) cy = head.biHeight;
\r
663 bool bTransparent = info.nBkgndIndex >= 0;
\r
664 bool bAlpha = pAlpha != 0;
\r
666 //required for MM_ANISOTROPIC, MM_HIENGLISH, and similar modes [Greg Peatfield]
\r
667 int hdc_Restore = ::SaveDC(hdc);
\r
671 #if !defined (_WIN32_WCE)
\r
672 RECT mainbox; // (experimental)
\r
674 GetClipBox(hdc,&mainbox);
\r
675 HRGN rgn = CreateRectRgnIndirect(pClipRect);
\r
676 ExtSelectClipRgn(hdc,rgn,RGN_AND);
\r
681 //find the smallest area to paint
\r
682 RECT clipbox,paintbox;
\r
683 GetClipBox(hdc,&clipbox);
\r
685 paintbox.top = min(clipbox.bottom,max(clipbox.top,y));
\r
686 paintbox.left = min(clipbox.right,max(clipbox.left,x));
\r
687 paintbox.right = max(clipbox.left,min(clipbox.right,x+cx));
\r
688 paintbox.bottom = max(clipbox.top,min(clipbox.bottom,y+cy));
\r
690 long destw = paintbox.right - paintbox.left;
\r
691 long desth = paintbox.bottom - paintbox.top;
\r
693 if (!(bTransparent || bAlpha || info.bAlphaPaletteEnabled)){
\r
694 if (cx==head.biWidth && cy==head.biHeight){ //NORMAL
\r
695 #if !defined (_WIN32_WCE)
\r
696 SetStretchBltMode(hdc,COLORONCOLOR);
\r
698 SetDIBitsToDevice(hdc, x, y, cx, cy, 0, 0, 0, cy,
\r
699 info.pImage,(BITMAPINFO*)pDib,DIB_RGB_COLORS);
\r
701 //pixel informations
\r
702 RGBQUAD c={0,0,0,0};
\r
703 //Preparing Bitmap Info
\r
705 memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
\r
706 bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
\r
707 bmInfo.bmiHeader.biWidth=destw;
\r
708 bmInfo.bmiHeader.biHeight=desth;
\r
709 bmInfo.bmiHeader.biPlanes=1;
\r
710 bmInfo.bmiHeader.biBitCount=24;
\r
711 BYTE *pbase; //points to the final dib
\r
712 BYTE *pdst; //current pixel from pbase
\r
713 BYTE *ppix; //current pixel from image
\r
714 //get the background
\r
715 HDC TmpDC=CreateCompatibleDC(hdc);
\r
716 HBITMAP TmpBmp=CreateDIBSection(hdc,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
\r
717 HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);
\r
725 long ew = ((((24 * destw) + 31) / 32) * 4);
\r
726 long ymax = paintbox.bottom;
\r
727 long xmin = paintbox.left;
\r
728 float fx=(float)head.biWidth/(float)cx;
\r
729 float fy=(float)head.biHeight/(float)cy;
\r
731 for(yy=0;yy<desth;yy++){
\r
732 dy = head.biHeight-(ymax-yy-y)*fy;
\r
733 sy = max(0L,(long)floor(dy));
\r
734 psrc = info.pImage+sy*info.dwEffWidth;
\r
735 pdst = pbase+yy*ew;
\r
736 for(xx=0;xx<destw;xx++){
\r
737 dx = (xx+xmin-x)*fx;
\r
738 sx = max(0L,(long)floor(dx));
\r
739 #if CXIMAGE_SUPPORT_INTERPOLATION
\r
741 if (fx > 1 && fy > 1) {
\r
742 c = GetAreaColorInterpolated(dx - 0.5f, dy - 0.5f, fx, fy, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
\r
744 c = GetPixelColorInterpolated(dx - 0.5f, dy - 0.5f, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
\r
747 #endif //CXIMAGE_SUPPORT_INTERPOLATION
\r
749 if (head.biClrUsed){
\r
750 c=GetPaletteColor(GetPixelIndex(sx,sy));
\r
752 ppix = psrc + sx*3;
\r
753 c.rgbBlue = *ppix++;
\r
754 c.rgbGreen= *ppix++;
\r
759 *pdst++=c.rgbGreen;
\r
764 //paint the image & cleanup
\r
765 SetDIBitsToDevice(hdc,paintbox.left,paintbox.top,destw,desth,0,0,0,desth,pbase,&bmInfo,0);
\r
766 DeleteObject(SelectObject(TmpDC,TmpObj));
\r
769 } else { // draw image with transparent/alpha blending
\r
770 //////////////////////////////////////////////////////////////////
\r
771 //Alpha blend - Thanks to Florian Egel
\r
773 //pixel informations
\r
774 RGBQUAD c={0,0,0,0};
\r
775 RGBQUAD ct = GetTransColor();
\r
776 long* pc = (long*)&c;
\r
777 long* pct= (long*)&ct;
\r
778 long cit = GetTransIndex();
\r
781 //Preparing Bitmap Info
\r
783 memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
\r
784 bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
\r
785 bmInfo.bmiHeader.biWidth=destw;
\r
786 bmInfo.bmiHeader.biHeight=desth;
\r
787 bmInfo.bmiHeader.biPlanes=1;
\r
788 bmInfo.bmiHeader.biBitCount=24;
\r
790 BYTE *pbase; //points to the final dib
\r
791 BYTE *pdst; //current pixel from pbase
\r
792 BYTE *ppix; //current pixel from image
\r
794 //get the background
\r
795 HDC TmpDC=CreateCompatibleDC(hdc);
\r
796 HBITMAP TmpBmp=CreateDIBSection(hdc,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
\r
797 HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);
\r
798 BitBlt(TmpDC,0,0,destw,desth,hdc,paintbox.left,paintbox.top,SRCCOPY);
\r
801 long xx,yy,alphaoffset,ix,iy;
\r
803 long ew = ((((24 * destw) + 31) / 32) * 4);
\r
804 long ymax = paintbox.bottom;
\r
805 long xmin = paintbox.left;
\r
807 if (cx!=head.biWidth || cy!=head.biHeight){
\r
809 float fx=(float)head.biWidth/(float)cx;
\r
810 float fy=(float)head.biHeight/(float)cy;
\r
814 for(yy=0;yy<desth;yy++){
\r
815 dy = head.biHeight-(ymax-yy-y)*fy;
\r
816 sy = max(0L,(long)floor(dy));
\r
818 alphaoffset = sy*head.biWidth;
\r
819 pdst = pbase + yy*ew;
\r
820 psrc = info.pImage + sy*info.dwEffWidth;
\r
822 for(xx=0;xx<destw;xx++){
\r
823 dx = (xx+xmin-x)*fx;
\r
824 sx = max(0L,(long)floor(dx));
\r
826 if (bAlpha) a=pAlpha[alphaoffset+sx]; else a=255;
\r
827 a =(BYTE)((a*(1+info.nAlphaMax))>>8);
\r
829 if (head.biClrUsed){
\r
830 ci = GetPixelIndex(sx,sy);
\r
831 #if CXIMAGE_SUPPORT_INTERPOLATION
\r
833 if (fx > 1 && fy > 1) {
\r
834 c = GetAreaColorInterpolated(dx - 0.5f, dy - 0.5f, fx, fy, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
\r
836 c = GetPixelColorInterpolated(dx - 0.5f, dy - 0.5f, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
\r
839 #endif //CXIMAGE_SUPPORT_INTERPOLATION
\r
841 c = GetPaletteColor(GetPixelIndex(sx,sy));
\r
843 if (info.bAlphaPaletteEnabled){
\r
844 a = (BYTE)((a*(1+c.rgbReserved))>>8);
\r
847 #if CXIMAGE_SUPPORT_INTERPOLATION
\r
849 if (fx > 1 && fy > 1) {
\r
850 c = GetAreaColorInterpolated(dx - 0.5f, dy - 0.5f, fx, fy, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
\r
852 c = GetPixelColorInterpolated(dx - 0.5f, dy - 0.5f, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
\r
855 #endif //CXIMAGE_SUPPORT_INTERPOLATION
\r
857 ppix = psrc + sx*3;
\r
858 c.rgbBlue = *ppix++;
\r
859 c.rgbGreen= *ppix++;
\r
863 //if (*pc!=*pct || !bTransparent){
\r
864 //if ((head.biClrUsed && ci!=cit) || ((!head.biClrUsed||bSmooth) && *pc!=*pct) || !bTransparent){
\r
865 if ((head.biClrUsed && ci!=cit) || (!head.biClrUsed && *pc!=*pct) || !bTransparent){
\r
866 // DJT, assume many pixels are fully transparent or opaque and thus avoid multiplication
\r
867 if (a == 0) { // Transparent, retain dest
\r
869 } else if (a == 255) { // opaque, ignore dest
\r
870 *pdst++= c.rgbBlue;
\r
871 *pdst++= c.rgbGreen;
\r
872 *pdst++= c.rgbRed;
\r
873 } else { // semi transparent
\r
875 *pdst++=(BYTE)((*pdst * a1 + a * c.rgbBlue)>>8);
\r
876 *pdst++=(BYTE)((*pdst * a1 + a * c.rgbGreen)>>8);
\r
877 *pdst++=(BYTE)((*pdst * a1 + a * c.rgbRed)>>8);
\r
886 iy=head.biHeight-ymax+y;
\r
887 for(yy=0;yy<desth;yy++,iy++){
\r
888 alphaoffset=iy*head.biWidth;
\r
891 ppix=info.pImage+iy*info.dwEffWidth+ix*3;
\r
892 for(xx=0;xx<destw;xx++,ix++){
\r
894 if (bAlpha) a=pAlpha[alphaoffset+ix]; else a=255;
\r
895 a = (BYTE)((a*(1+info.nAlphaMax))>>8);
\r
897 if (head.biClrUsed){
\r
898 ci = GetPixelIndex(ix,iy);
\r
899 c = GetPaletteColor((BYTE)ci);
\r
900 if (info.bAlphaPaletteEnabled){
\r
901 a = (BYTE)((a*(1+c.rgbReserved))>>8);
\r
904 c.rgbBlue = *ppix++;
\r
905 c.rgbGreen= *ppix++;
\r
906 c.rgbRed = *ppix++;
\r
909 //if (*pc!=*pct || !bTransparent){
\r
910 if ((head.biClrUsed && ci!=cit) || (!head.biClrUsed && *pc!=*pct) || !bTransparent){
\r
911 // DJT, assume many pixels are fully transparent or opaque and thus avoid multiplication
\r
912 if (a == 0) { // Transparent, retain dest
\r
914 } else if (a == 255) { // opaque, ignore dest
\r
915 *pdst++= c.rgbBlue;
\r
916 *pdst++= c.rgbGreen;
\r
917 *pdst++= c.rgbRed;
\r
918 } else { // semi transparent
\r
920 *pdst++=(BYTE)((*pdst * a1 + a * c.rgbBlue)>>8);
\r
921 *pdst++=(BYTE)((*pdst * a1 + a * c.rgbGreen)>>8);
\r
922 *pdst++=(BYTE)((*pdst * a1 + a * c.rgbRed)>>8);
\r
931 //paint the image & cleanup
\r
932 SetDIBitsToDevice(hdc,paintbox.left,paintbox.top,destw,desth,0,0,0,desth,pbase,&bmInfo,0);
\r
933 DeleteObject(SelectObject(TmpDC,TmpObj));
\r
937 #if !defined (_WIN32_WCE)
\r
938 if (pClipRect){ // (experimental)
\r
939 HRGN rgn = CreateRectRgnIndirect(&mainbox);
\r
940 ExtSelectClipRgn(hdc,rgn,RGN_OR);
\r
945 ::RestoreDC(hdc,hdc_Restore);
\r
948 ////////////////////////////////////////////////////////////////////////////////
\r
949 long CxImage::Draw2(HDC hdc, const RECT& rect)
\r
951 return Draw2(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
\r
953 ////////////////////////////////////////////////////////////////////////////////
\r
955 * Draws (stretch) the image with single transparency support
\r
956 * \param hdc : destination device context
\r
957 * \param x,y : (optional) offset
\r
958 * \param cx,cy : (optional) size.
\r
959 * - If cx or cy are not specified (or less than 0), the normal width or height will be used
\r
960 * - If cx or cy are different than width or height, the image will be stretched
\r
962 * \return true if everything is ok
\r
964 long CxImage::Draw2(HDC hdc, long x, long y, long cx, long cy)
\r
966 if((pDib==0)||(hdc==0)||(cx==0)||(cy==0)||(!info.bEnabled)) return 0;
\r
967 if (cx < 0) cx = head.biWidth;
\r
968 if (cy < 0) cy = head.biHeight;
\r
969 bool bTransparent = (info.nBkgndIndex >= 0);
\r
971 //required for MM_ANISOTROPIC, MM_HIENGLISH, and similar modes [Greg Peatfield]
\r
972 int hdc_Restore = ::SaveDC(hdc);
\r
976 if (!bTransparent){
\r
977 #if !defined (_WIN32_WCE)
\r
978 SetStretchBltMode(hdc,COLORONCOLOR);
\r
980 StretchDIBits(hdc, x, y, cx, cy, 0, 0, head.biWidth, head.biHeight,
\r
981 info.pImage,(BITMAPINFO*)pDib, DIB_RGB_COLORS,SRCCOPY);
\r
983 // draw image with transparent background
\r
984 const int safe = 0; // or else GDI fails in the following - sometimes
\r
985 RECT rcDst = {x+safe, y+safe, x+cx, y+cy};
\r
986 if (RectVisible(hdc, &rcDst)){
\r
987 /////////////////////////////////////////////////////////////////
\r
988 // True Mask Method - Thanks to Paul Reynolds and Ron Gery
\r
989 int nWidth = head.biWidth;
\r
990 int nHeight = head.biHeight;
\r
991 // Create two memory dcs for the image and the mask
\r
992 HDC dcImage=CreateCompatibleDC(hdc);
\r
993 HDC dcTrans=CreateCompatibleDC(hdc);
\r
994 // Select the image into the appropriate dc
\r
995 HBITMAP bm = CreateCompatibleBitmap(hdc, nWidth, nHeight);
\r
996 HBITMAP pOldBitmapImage = (HBITMAP)SelectObject(dcImage,bm);
\r
997 #if !defined (_WIN32_WCE)
\r
998 SetStretchBltMode(dcImage,COLORONCOLOR);
\r
1000 StretchDIBits(dcImage, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
\r
1001 info.pImage,(BITMAPINFO*)pDib,DIB_RGB_COLORS,SRCCOPY);
\r
1003 // Create the mask bitmap
\r
1004 HBITMAP bitmapTrans = CreateBitmap(nWidth, nHeight, 1, 1, NULL);
\r
1005 // Select the mask bitmap into the appropriate dc
\r
1006 HBITMAP pOldBitmapTrans = (HBITMAP)SelectObject(dcTrans, bitmapTrans);
\r
1007 // Build mask based on transparent colour
\r
1009 if (head.biBitCount<24) rgbBG = GetPaletteColor((BYTE)info.nBkgndIndex);
\r
1010 else rgbBG = info.nBkgndColor;
\r
1011 COLORREF crColour = RGB(rgbBG.rgbRed, rgbBG.rgbGreen, rgbBG.rgbBlue);
\r
1012 COLORREF crOldBack = SetBkColor(dcImage,crColour);
\r
1013 BitBlt(dcTrans,0, 0, nWidth, nHeight, dcImage, 0, 0, SRCCOPY);
\r
1015 // Do the work - True Mask method - cool if not actual display
\r
1016 StretchBlt(hdc,x, y,cx,cy, dcImage, 0, 0, nWidth, nHeight, SRCINVERT);
\r
1017 StretchBlt(hdc,x, y,cx,cy, dcTrans, 0, 0, nWidth, nHeight, SRCAND);
\r
1018 StretchBlt(hdc,x, y,cx,cy, dcImage, 0, 0, nWidth, nHeight, SRCINVERT);
\r
1020 // Restore settings
\r
1021 SelectObject(dcImage,pOldBitmapImage);
\r
1022 SelectObject(dcTrans,pOldBitmapTrans);
\r
1023 SetBkColor(hdc,crOldBack);
\r
1024 DeleteObject( bitmapTrans ); // RG 29/01/2002
\r
1025 DeleteDC(dcImage);
\r
1026 DeleteDC(dcTrans);
\r
1030 ::RestoreDC(hdc,hdc_Restore);
\r
1033 ////////////////////////////////////////////////////////////////////////////////
\r
1034 long CxImage::Stretch(HDC hdc, const RECT& rect, DWORD dwRop)
\r
1036 return Stretch(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, dwRop);
\r
1038 ////////////////////////////////////////////////////////////////////////////////
\r
1040 * Stretch the image. Obsolete: use Draw() or Draw2()
\r
1041 * \param hdc : destination device context
\r
1042 * \param xoffset,yoffset : (optional) offset
\r
1043 * \param xsize,ysize : size.
\r
1044 * \param dwRop : raster operation code (see BitBlt documentation)
\r
1045 * \return true if everything is ok
\r
1047 long CxImage::Stretch(HDC hdc, long xoffset, long yoffset, long xsize, long ysize, DWORD dwRop)
\r
1049 if((pDib)&&(hdc)) {
\r
1050 //palette must be correctly filled
\r
1051 #if !defined (_WIN32_WCE)
\r
1052 SetStretchBltMode(hdc,COLORONCOLOR);
\r
1054 StretchDIBits(hdc, xoffset, yoffset,
\r
1055 xsize, ysize, 0, 0, head.biWidth, head.biHeight,
\r
1056 info.pImage,(BITMAPINFO*)pDib,DIB_RGB_COLORS,dwRop);
\r
1061 ////////////////////////////////////////////////////////////////////////////////
\r
1063 * Tiles the device context in the specified rectangle with the image.
\r
1064 * \param hdc : destination device context
\r
1065 * \param rc : tiled rectangle in the output device context
\r
1066 * \return true if everything is ok
\r
1068 long CxImage::Tile(HDC hdc, RECT *rc)
\r
1070 if((pDib)&&(hdc)&&(rc)) {
\r
1071 int w = rc->right - rc->left;
\r
1072 int h = rc->bottom - rc->top;
\r
1074 int bx=head.biWidth;
\r
1075 int by=head.biHeight;
\r
1076 for (y = 0 ; y < h ; y += by){
\r
1077 if ((y+by)>h) by=h-y;
\r
1079 for (x = 0 ; x < w ; x += z){
\r
1080 if ((x+z)>w) z=w-x;
\r
1081 RECT r = {rc->left + x,rc->top + y,rc->left + x + z,rc->top + y + by};
\r
1082 Draw(hdc,rc->left + x, rc->top + y,-1,-1,&r);
\r
1089 ////////////////////////////////////////////////////////////////////////////////
\r
1090 // For UNICODE support: char -> TCHAR
\r
1091 long CxImage::DrawString(HDC hdc, long x, long y, const TCHAR* text, RGBQUAD color, const TCHAR* font, long lSize, long lWeight, BYTE bItalic, BYTE bUnderline, bool bSetAlpha)
\r
1092 //long CxImage::DrawString(HDC hdc, long x, long y, const char* text, RGBQUAD color, const char* font, long lSize, long lWeight, BYTE bItalic, BYTE bUnderline, bool bSetAlpha)
\r
1095 //get the background
\r
1097 if (hdc) pDC=hdc; else pDC = ::GetDC(0);
\r
1098 if (pDC==NULL) return 0;
\r
1099 HDC TmpDC=CreateCompatibleDC(pDC);
\r
1100 if (hdc==NULL) ::ReleaseDC(0, pDC);
\r
1101 if (TmpDC==NULL) return 0;
\r
1105 m_pLF=(LOGFONT*)calloc(1,sizeof(LOGFONT));
\r
1106 _tcsncpy(m_pLF->lfFaceName,font,31); // For UNICODE support
\r
1107 //strncpy(m_pLF->lfFaceName,font,31);
\r
1108 m_pLF->lfHeight=lSize;
\r
1109 m_pLF->lfWeight=lWeight;
\r
1110 m_pLF->lfItalic=bItalic;
\r
1111 m_pLF->lfUnderline=bUnderline;
\r
1112 m_Font=CreateFontIndirect(m_pLF);
\r
1113 //select the font in the dc
\r
1114 HFONT pOldFont=NULL;
\r
1116 pOldFont = (HFONT)SelectObject(TmpDC,m_Font);
\r
1118 pOldFont = (HFONT)SelectObject(TmpDC,GetStockObject(DEFAULT_GUI_FONT));
\r
1121 SetTextColor(TmpDC,RGB(255,255,255));
\r
1122 SetBkColor(TmpDC,RGB(0,0,0));
\r
1124 SetBkMode(TmpDC,OPAQUE);
\r
1125 //Set text position;
\r
1126 RECT pos = {0,0,0,0};
\r
1127 //long len = (long)strlen(text);
\r
1128 long len = (long)_tcslen(text); // For UNICODE support
\r
1129 ::DrawText(TmpDC,text,len,&pos,DT_CALCRECT);
\r
1130 pos.right+=pos.bottom; //for italics
\r
1132 //Preparing Bitmap Info
\r
1133 long width=pos.right;
\r
1134 long height=pos.bottom;
\r
1135 BITMAPINFO bmInfo;
\r
1136 memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
\r
1137 bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
\r
1138 bmInfo.bmiHeader.biWidth=width;
\r
1139 bmInfo.bmiHeader.biHeight=height;
\r
1140 bmInfo.bmiHeader.biPlanes=1;
\r
1141 bmInfo.bmiHeader.biBitCount=24;
\r
1142 BYTE *pbase; //points to the final dib
\r
1144 HBITMAP TmpBmp=CreateDIBSection(TmpDC,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
\r
1145 HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);
\r
1146 memset(pbase,0,height*((((24 * width) + 31) / 32) * 4));
\r
1148 ::DrawText(TmpDC,text,len,&pos,0);
\r
1151 itext.CreateFromHBITMAP(TmpBmp);
\r
1153 y=head.biHeight-y-1;
\r
1154 for (long ix=0;ix<width;ix++){
\r
1155 for (long iy=0;iy<height;iy++){
\r
1156 if (itext.GetPixelColor(ix,iy).rgbBlue) SetPixelColor(x+ix,y+iy,color,bSetAlpha);
\r
1161 if (pOldFont) SelectObject(TmpDC,pOldFont);
\r
1162 DeleteObject(m_Font);
\r
1164 DeleteObject(SelectObject(TmpDC,TmpObj));
\r
1170 ////////////////////////////////////////////////////////////////////////////////
\r
1172 long CxImage::DrawStringEx(HDC hdc, long x, long y, CXTEXTINFO *pTextType, bool bSetAlpha )
\r
1177 //get the background
\r
1179 if (hdc) pDC=hdc; else pDC = ::GetDC(0);
\r
1180 if (pDC==NULL) return 0;
\r
1181 HDC TmpDC=CreateCompatibleDC(pDC);
\r
1182 if (hdc==NULL) ::ReleaseDC(0, pDC);
\r
1183 if (TmpDC==NULL) return 0;
\r
1187 m_Font=CreateFontIndirect( &pTextType->lfont );
\r
1189 // get colors in RGBQUAD
\r
1190 RGBQUAD p_forecolor = RGBtoRGBQUAD(pTextType->fcolor);
\r
1191 RGBQUAD p_backcolor = RGBtoRGBQUAD(pTextType->bcolor);
\r
1193 // check alignment and re-set default if necessary
\r
1194 if ( pTextType->align != DT_CENTER &&
\r
1195 pTextType->align != DT_LEFT &&
\r
1196 pTextType->align != DT_RIGHT )
\r
1197 pTextType->align = DT_CENTER;
\r
1199 // check rounding radius and re-set default if necessary
\r
1200 if ( pTextType->b_round > 50 )
\r
1201 pTextType->b_round = 10;
\r
1203 // check opacity and re-set default if necessary
\r
1204 if ( pTextType->b_opacity > 1. || pTextType->b_opacity < .0 )
\r
1205 pTextType->b_opacity = 0.;
\r
1207 //select the font in the dc
\r
1208 HFONT pOldFont=NULL;
\r
1210 pOldFont = (HFONT)SelectObject(TmpDC,m_Font);
\r
1212 pOldFont = (HFONT)SelectObject(TmpDC,GetStockObject(DEFAULT_GUI_FONT));
\r
1215 SetTextColor(TmpDC,RGB(255,255,255));
\r
1216 SetBkColor(TmpDC,RGB(0,0,0));
\r
1217 SetBkMode(TmpDC,OPAQUE);
\r
1218 //Set text position;
\r
1219 RECT pos = {0,0,0,0};
\r
1221 // get text length and number of lines
\r
1222 long i=0, numlines=1, len=(long)_tcsclen(pTextType->text);
\r
1225 if ( pTextType->text[i++]==13 )
\r
1229 ::DrawText(TmpDC, pTextType->text, len, &pos, /*DT_EDITCONTROL|DT_EXTERNALLEADING|*/DT_NOPREFIX | DT_CALCRECT );
\r
1231 // increase only if it's really italics, and only one line height
\r
1232 if ( pTextType->lfont.lfItalic )
\r
1233 pos.right += pos.bottom/2/numlines;
\r
1235 // background frame and rounding radius
\r
1236 int frame = 0, roundR = 0;
\r
1237 if ( pTextType->opaque )
\r
1239 roundR= (int)(pos.bottom/numlines * pTextType->b_round / 100 ) ;
\r
1240 frame = (int)(/*3.5 + */0.29289*roundR ) ;
\r
1241 pos.right += pos.bottom/numlines/3 ; // JUST FOR BEAUTY
\r
1244 //Preparing Bitmap Info
\r
1245 long width=pos.right +frame*2;
\r
1246 long height=pos.bottom +frame*2;
\r
1247 BITMAPINFO bmInfo;
\r
1248 memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
\r
1249 bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
\r
1250 bmInfo.bmiHeader.biWidth=width;
\r
1251 bmInfo.bmiHeader.biHeight=height;
\r
1252 bmInfo.bmiHeader.biPlanes=1;
\r
1253 bmInfo.bmiHeader.biBitCount=24;
\r
1254 BYTE *pbase; //points to the final dib
\r
1256 HBITMAP TmpBmp=CreateDIBSection(TmpDC,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
\r
1257 HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);
\r
1258 memset(pbase,0,height*((((24 * width) + 31) / 32) * 4));
\r
1260 ::DrawText(TmpDC,pTextType->text,len, &pos, /*DT_EDITCONTROL|DT_EXTERNALLEADING|*/DT_NOPREFIX| pTextType->align );
\r
1263 itext.CreateFromHBITMAP(TmpBmp);
\r
1264 y=head.biHeight-y-1;
\r
1268 if (pTextType->smooth==FALSE){
\r
1269 itext.Threshold(128);
\r
1271 //itext.TextBlur();
\r
1274 //move the insertion point according to alignment type
\r
1275 // DT_CENTER: cursor points to the center of text rectangle
\r
1276 // DT_RIGHT: cursor points to right side end of text rectangle
\r
1277 // DT_LEFT: cursor points to left end of text rectangle
\r
1278 if ( pTextType->align == DT_CENTER )
\r
1280 else if ( pTextType->align == DT_RIGHT )
\r
1284 //draw the background first, if it exists
\r
1286 if ( pTextType->opaque )
\r
1289 for (ix=0;ix<width;ix++)
\r
1292 ixf = (int)(.5+roundR-sqrt((float)(roundR*roundR-(ix-roundR)*(ix-roundR))));
\r
1293 else if ( ix>=width-roundR-1 )
\r
1294 ixf = (int)(.5+roundR-sqrt((float)(roundR*roundR-(width-1-ix-roundR)*(width-1-ix-roundR))));
\r
1298 for (iy=0;iy<height;iy++)
\r
1300 if ( (ix<=roundR && ( iy > height-ixf-1 || iy < ixf )) ||
\r
1301 (ix>=width-roundR-1 && ( iy > height-ixf-1 || iy < ixf )) )
\r
1304 if ( pTextType->b_opacity > 0.0 && pTextType->b_opacity < 1.0 )
\r
1306 RGBQUAD bcolor, pcolor;
\r
1307 // calculate a transition color from original image to background color:
\r
1308 pcolor = GetPixelColor(x+ix,y+iy);
\r
1309 bcolor.rgbBlue = (unsigned char)(pTextType->b_opacity * pcolor.rgbBlue + (1.0-pTextType->b_opacity) * p_backcolor.rgbBlue );
\r
1310 bcolor.rgbRed = (unsigned char)(pTextType->b_opacity * pcolor.rgbRed + (1.0-pTextType->b_opacity) * p_backcolor.rgbRed ) ;
\r
1311 bcolor.rgbGreen = (unsigned char)(pTextType->b_opacity * pcolor.rgbGreen + (1.0-pTextType->b_opacity) * p_backcolor.rgbGreen ) ;
\r
1312 bcolor.rgbReserved = 0;
\r
1313 SetPixelColor(x+ix,y+iy,bcolor,bSetAlpha);
\r
1316 SetPixelColor(x+ix,y+iy,p_backcolor,bSetAlpha);
\r
1321 // draw the text itself
\r
1322 for (ix=0;ix<width;ix++)
\r
1324 for (iy=0;iy<height;iy++)
\r
1326 RGBQUAD pcolor = GetPixelColor(x+ix,y+iy);
\r
1327 RGBQUAD tcolor = itext.GetPixelColor(ix,iy);
\r
1328 if (tcolor.rgbBlue!=255){
\r
1329 float a = tcolor.rgbBlue/255.0f;
\r
1330 pcolor.rgbBlue = (unsigned char)(a * (pcolor.rgbBlue - p_forecolor.rgbBlue) + p_forecolor.rgbBlue );
\r
1331 pcolor.rgbRed = (unsigned char)(a * (pcolor.rgbRed - p_forecolor.rgbRed) + p_forecolor.rgbRed ) ;
\r
1332 pcolor.rgbGreen = (unsigned char)(a * (pcolor.rgbGreen - p_forecolor.rgbGreen) + p_forecolor.rgbGreen );
\r
1333 pcolor.rgbReserved = 0;
\r
1334 SetPixelColor(x+ix+frame,y+iy-frame,pcolor,bSetAlpha);
\r
1335 //SetPixelColor(x+ix+frame,y+iy-frame,p_forecolor,bSetAlpha);
\r
1341 if (pOldFont) SelectObject(TmpDC,pOldFont);
\r
1342 DeleteObject(m_Font);
\r
1343 DeleteObject(SelectObject(TmpDC,TmpObj));
\r
1348 //////////////////////////////////////////////////////////////////////////////
\r
1349 void CxImage::InitTextInfo( CXTEXTINFO *txt )
\r
1352 memset( txt, 0, sizeof(CXTEXTINFO));
\r
1354 // LOGFONT defaults
\r
1355 txt->lfont.lfHeight = -36;
\r
1356 txt->lfont.lfCharSet = EASTEUROPE_CHARSET; // just for Central-European users
\r
1357 txt->lfont.lfWeight = FW_NORMAL;
\r
1358 txt->lfont.lfWidth = 0;
\r
1359 txt->lfont.lfEscapement = 0;
\r
1360 txt->lfont.lfOrientation = 0;
\r
1361 txt->lfont.lfItalic = FALSE;
\r
1362 txt->lfont.lfUnderline = FALSE;
\r
1363 txt->lfont.lfStrikeOut = FALSE;
\r
1364 txt->lfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
\r
1365 txt->lfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
\r
1366 txt->lfont.lfQuality = PROOF_QUALITY;
\r
1367 txt->lfont.lfPitchAndFamily= DEFAULT_PITCH | FF_DONTCARE ;
\r
1368 _stprintf( txt->lfont.lfFaceName, _T("Arial")); //use TCHAR mappings <Cesar M>
\r
1371 txt->fcolor = RGB( 255,255,160 ); // default foreground: light goldyellow
\r
1372 txt->bcolor = RGB( 0, 80,160 ); // default background: light blue
\r
1375 txt->opaque = TRUE; // text has a non-transparent background;
\r
1376 txt->smooth = TRUE;
\r
1377 txt->b_opacity = 0.0; // default: opaque background
\r
1378 txt->b_outline = 0; // default: no outline (OUTLINE NOT IMPLEMENTED AT THIS TIME)
\r
1379 txt->b_round = 20; // default: rounding radius is 20% of the rectangle height
\r
1381 _stprintf( txt->text, _T("Sample Text 01234รตรป")); // text use TCHAR mappings <Cesar M>
\r
1382 txt->align = DT_CENTER;
\r
1386 #if CXIMAGE_SUPPORT_LAYERS
\r
1387 ////////////////////////////////////////////////////////////////////////////////
\r
1388 long CxImage::LayerDrawAll(HDC hdc, const RECT& rect, RECT* pClipRect, bool bSmooth)
\r
1390 return LayerDrawAll(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pClipRect,bSmooth);
\r
1392 ////////////////////////////////////////////////////////////////////////////////
\r
1393 long CxImage::LayerDrawAll(HDC hdc, long x, long y, long cx, long cy, RECT* pClipRect, bool bSmooth)
\r
1397 while(pLayer=GetLayer(n++)){
\r
1398 if (pLayer->Draw(hdc,x+pLayer->info.xOffset,y+pLayer->info.yOffset,cx,cy,pClipRect,bSmooth)==0)
\r
1400 if (pLayer->LayerDrawAll(hdc,x+pLayer->info.xOffset,y+pLayer->info.yOffset,cx,cy,pClipRect,bSmooth)==0)
\r
1405 #endif //CXIMAGE_SUPPORT_LAYERS
\r
1407 ////////////////////////////////////////////////////////////////////////////////
\r
1408 #endif //CXIMAGE_SUPPORT_WINDOWS
\r
1409 ////////////////////////////////////////////////////////////////////////////////
\r