Index: MUSHclient.cpp =================================================================== RCS file: /cvs/mushclient/MUSHclient.cpp,v retrieving revision 1.91 retrieving revision 1.92 diff -c -r1.91 -r1.92 *** MUSHclient.cpp 27 Jun 2008 21:35:50 -0000 1.91 --- MUSHclient.cpp 24 Aug 2008 04:50:48 -0000 1.92 *************** *** 505,525 **** // try to set up for DirectSound if (FAILED (DirectSoundCreate (NULL, &m_pDirectSoundObject, NULL))) m_pDirectSoundObject = NULL; // set sound cooperation level ! if (FAILED (m_pDirectSoundObject->SetCooperativeLevel (pMainFrame->m_hWnd, DSSCL_NORMAL))) ! m_pDirectSoundObject = NULL; // no DirectSound } ! DSBUFFERDESC bd; - memset (&bd, 0, sizeof (DSBUFFERDESC)); - bd.dwSize = sizeof (DSBUFFERDESC); - bd.dwFlags = DSBCAPS_PRIMARYBUFFER; - bd.dwBufferBytes = 0; //must be 0 for primary buffer - bd.lpwfxFormat = NULL; //must be null for primary buffer ! if (FAILED (m_pDirectSoundObject->CreateSoundBuffer (&bd, &m_pDirectSoundPrimaryBuffer, NULL))) ! m_pDirectSoundObject = NULL; // no DirectSound // see which OS we are using --- 505,531 ---- // try to set up for DirectSound if (FAILED (DirectSoundCreate (NULL, &m_pDirectSoundObject, NULL))) m_pDirectSoundObject = NULL; + // set sound cooperation level ! if (m_pDirectSoundObject) ! if (FAILED (m_pDirectSoundObject->SetCooperativeLevel (pMainFrame->m_hWnd, DSSCL_NORMAL))) ! m_pDirectSoundObject = NULL; // no DirectSound } ! if (m_pDirectSoundObject) ! { ! DSBUFFERDESC bd; ! ! memset (&bd, 0, sizeof (DSBUFFERDESC)); ! bd.dwSize = sizeof (DSBUFFERDESC); ! bd.dwFlags = DSBCAPS_PRIMARYBUFFER; ! bd.dwBufferBytes = 0; //must be 0 for primary buffer ! bd.lpwfxFormat = NULL; //must be null for primary buffer ! if (FAILED (m_pDirectSoundObject->CreateSoundBuffer (&bd, &m_pDirectSoundPrimaryBuffer, NULL))) ! m_pDirectSoundObject = NULL; // no DirectSound ! } // see which OS we are using Index: MUSHclient.dsp =================================================================== RCS file: /cvs/mushclient/MUSHclient.dsp,v retrieving revision 1.100 retrieving revision 1.101 diff -c -r1.100 -r1.101 *** MUSHclient.dsp 16 Jul 2008 20:52:28 -0000 1.100 --- MUSHclient.dsp 29 Aug 2008 03:33:41 -0000 1.101 *************** *** 1473,1486 **** # SUBTRACT CPP /YX /Yc /Yu # End Source File # End Group # Begin Source File SOURCE=.\install\readme.txt # End Source File # End Target # End Project ! # Section MUSHclient : {00000000-0001-0000-0000-000000000000} ! # 1:23:CG_IDR_POPUP_MAIN_FRAME:126 # End Section # Section MUSHclient : {F3B13065-16CC-11D0-B7D0-00A0247B3BFD} # 0:8:TipDlg.h:D:\SOURCE\MUSHclient\TipDlg.h --- 1473,1585 ---- # SUBTRACT CPP /YX /Yc /Yu # End Source File # End Group + # Begin Group "PNG" + + # PROP Default_Filter "" + # Begin Source File + + SOURCE=.\png.c + # SUBTRACT CPP /YX /Yc /Yu + # End Source File + # Begin Source File + + SOURCE=.\pngerror.c + # SUBTRACT CPP /YX /Yc /Yu + # End Source File + # Begin Source File + + SOURCE=.\pnggccrd.c + # SUBTRACT CPP /YX /Yc /Yu + # End Source File + # Begin Source File + + SOURCE=.\pngget.c + # SUBTRACT CPP /YX /Yc /Yu + # End Source File + # Begin Source File + + SOURCE=.\pngmem.c + # SUBTRACT CPP /YX /Yc /Yu + # End Source File + # Begin Source File + + SOURCE=.\pngpread.c + # SUBTRACT CPP /YX /Yc /Yu + # End Source File + # Begin Source File + + SOURCE=.\pngread.c + # SUBTRACT CPP /YX /Yc /Yu + # End Source File + # Begin Source File + + SOURCE=.\pngrio.c + # SUBTRACT CPP /YX /Yc /Yu + # End Source File + # Begin Source File + + SOURCE=.\pngrtran.c + # SUBTRACT CPP /YX /Yc /Yu + # End Source File + # Begin Source File + + SOURCE=.\pngrutil.c + # SUBTRACT CPP /YX /Yc /Yu + # End Source File + # Begin Source File + + SOURCE=.\pngset.c + # SUBTRACT CPP /YX /Yc /Yu + # End Source File + # Begin Source File + + SOURCE=.\pngtrans.c + # SUBTRACT CPP /YX /Yc /Yu + # End Source File + # Begin Source File + + SOURCE=.\pngvcrd.c + # SUBTRACT CPP /YX /Yc /Yu + # End Source File + # Begin Source File + + SOURCE=.\pngwio.c + # SUBTRACT CPP /YX /Yc /Yu + # End Source File + # Begin Source File + + SOURCE=.\pngwrite.c + # SUBTRACT CPP /YX /Yc /Yu + # End Source File + # Begin Source File + + SOURCE=.\pngwtran.c + # SUBTRACT CPP /YX /Yc /Yu + # End Source File + # Begin Source File + + SOURCE=.\pngwutil.c + # SUBTRACT CPP /YX /Yc /Yu + # End Source File + # End Group # Begin Source File SOURCE=.\install\readme.txt # End Source File # End Target # End Project ! # Section MUSHclient : {F3B1306C-16CC-11D0-B7D0-00A0247B3BFD} ! # 0:8:Splash.h:D:\SOURCE\MUSHclient\Splash.h ! # 0:10:Splash.cpp:D:\SOURCE\MUSHclient\Splash.cpp ! # 1:10:IDB_SPLASH:102 ! # 2:10:ResHdrName:resource.h ! # 2:11:ProjHdrName:stdafx.h ! # 2:10:WrapperDef:_SPLASH_SCRN_ ! # 2:12:SplClassName:CSplashWnd ! # 2:21:SplashScreenInsertKey:4.0 ! # 2:10:HeaderName:Splash.h ! # 2:10:ImplemName:Splash.cpp ! # 2:7:BmpID16:IDB_SPLASH # End Section # Section MUSHclient : {F3B13065-16CC-11D0-B7D0-00A0247B3BFD} # 0:8:TipDlg.h:D:\SOURCE\MUSHclient\TipDlg.h *************** *** 1507,1525 **** # 2:18:CG_IDS_FILE_ABSENT:CG_IDS_FILE_ABSENT # 2:10:TipDlg.cpp:TipDlg.cpp # End Section - # Section MUSHclient : {F3B1306C-16CC-11D0-B7D0-00A0247B3BFD} - # 0:8:Splash.h:D:\SOURCE\MUSHclient\Splash.h - # 0:10:Splash.cpp:D:\SOURCE\MUSHclient\Splash.cpp - # 1:10:IDB_SPLASH:102 - # 2:10:ResHdrName:resource.h - # 2:11:ProjHdrName:stdafx.h - # 2:10:WrapperDef:_SPLASH_SCRN_ - # 2:12:SplClassName:CSplashWnd - # 2:21:SplashScreenInsertKey:4.0 - # 2:10:HeaderName:Splash.h - # 2:10:ImplemName:Splash.cpp - # 2:7:BmpID16:IDB_SPLASH - # End Section # Section MUSHclient : {00000000-0000-0000-0000-000000000000} # 1:22:CG_IDR_POPUP_SEND_VIEW:124 # End Section --- 1606,1611 ---- *************** *** 1528,1531 **** --- 1614,1620 ---- # End Section # Section MUSHclient : {00000000-000C-0000-0C00-00004944445F} # 1:26:CG_IDR_POPUP_ACTIVITY_VIEW:127 + # End Section + # Section MUSHclient : {00000000-0001-0000-0000-000000000000} + # 1:23:CG_IDR_POPUP_MAIN_FRAME:126 # End Section Index: MUSHclient.rc =================================================================== RCS file: /cvs/mushclient/MUSHclient.rc,v retrieving revision 1.227 retrieving revision 1.228 diff -c -r1.227 -r1.228 *** MUSHclient.rc 6 Aug 2008 02:35:17 -0000 1.227 --- MUSHclient.rc 12 Aug 2008 01:29:06 -0000 1.228 *************** *** 75,82 **** // VS_VERSION_INFO VERSIONINFO ! FILEVERSION 4,0,35,0 ! PRODUCTVERSION 4,0,35,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L --- 75,82 ---- // VS_VERSION_INFO VERSIONINFO ! FILEVERSION 4,0,36,0 ! PRODUCTVERSION 4,0,36,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L *************** *** 94,107 **** VALUE "Comments", "MUSHclient - a client program for playing MUD games\0" VALUE "CompanyName", "Gammon Software Solutions\0" VALUE "FileDescription", "MUSHclient\0" ! VALUE "FileVersion", "4.35\0" VALUE "InternalName", "MUSHCLIENT\0" VALUE "LegalCopyright", "Copyright © 2008 Gammon Software Solutions\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "MUSHCLIENT.EXE\0" VALUE "PrivateBuild", "\0" VALUE "ProductName", "MUSHclient\0" ! VALUE "ProductVersion", "4.35\0" VALUE "SpecialBuild", "\0" END END --- 94,107 ---- VALUE "Comments", "MUSHclient - a client program for playing MUD games\0" VALUE "CompanyName", "Gammon Software Solutions\0" VALUE "FileDescription", "MUSHclient\0" ! VALUE "FileVersion", "4.36\0" VALUE "InternalName", "MUSHCLIENT\0" VALUE "LegalCopyright", "Copyright © 2008 Gammon Software Solutions\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "MUSHCLIENT.EXE\0" VALUE "PrivateBuild", "\0" VALUE "ProductName", "MUSHclient\0" ! VALUE "ProductVersion", "4.36\0" VALUE "SpecialBuild", "\0" END END Index: Mapping.cpp =================================================================== RCS file: /cvs/mushclient/Mapping.cpp,v retrieving revision 1.14 retrieving revision 1.15 diff -c -r1.14 -r1.15 *** Mapping.cpp 13 Jun 2007 17:57:28 -0000 1.14 --- Mapping.cpp 12 Aug 2008 01:29:06 -0000 1.15 *************** *** 167,176 **** else strComment.Empty (); ! // if this is the reverse direction, remove the earlier one rather than ! // adding this one ! if (m_strMapList.GetTail () == i->second.m_sReverseDirection.c_str ()) m_strMapList.RemoveTail (); else { // different direction? Put comment back if we had one --- 167,192 ---- else strComment.Empty (); ! // if this direction had a non-standard reverse, extract that ! CString strLast = m_strMapList.GetTail (); ! ! int iSlashPos = strLast.Find ("/"); ! if (iSlashPos != -1) ! { ! strLast = strLast.Mid (iSlashPos + 1); // this is the reverse direction ! ! MapDirectionsIterator i2; ! ! i2 = MapDirectionsMap.find ((LPCTSTR) strLast); // convert "west" to "w" ! ! // if this is the reverse direction, remove the earlier one rather than ! // adding this one ! if (i2 != MapDirectionsMap.end () && ! i2->second.m_sDirectionToLog == i->second.m_sDirectionToLog) m_strMapList.RemoveTail (); + } + else if (m_strMapList.GetTail () == i->second.m_sReverseDirection.c_str ()) + m_strMapList.RemoveTail (); else { // different direction? Put comment back if we had one Index: OtherTypes.h =================================================================== RCS file: /cvs/mushclient/OtherTypes.h,v retrieving revision 1.99 retrieving revision 1.102 diff -c -r1.99 -r1.102 *** OtherTypes.h 5 Aug 2008 06:25:12 -0000 1.99 --- OtherTypes.h 26 Aug 2008 05:23:14 -0000 1.102 *************** *** 966,971 **** --- 966,972 ---- DISPID m_dispid_plugin_packet_received; // "OnPluginPacketReceived" DISPID m_dispid_plugin_partial_line; // "OnPluginPartialLine" DISPID m_dispid_plugin_telnet_option; // "OnPluginTelnetOption" + DISPID m_dispid_plugin_on_world_output_resized; // "OnPluginWorldOutputResized" DISPID m_dispid_plugin_OnMXP_Start; // "OnPluginMXPstart" DISPID m_dispid_plugin_OnMXP_Stop; // "OnPluginMXPstop" *************** *** 981,987 **** DISPID m_dispid_plugin_On_Chat_Display; // "OnPluginChatDisplay" DISPID m_dispid_plugin_On_Chat_NewUser; // "OnPluginChatNewUser" DISPID m_dispid_plugin_On_Chat_UserDisconnect; // "OnPluginChatUserDisconnect" - // methods CPlugin (CMUSHclientDoc * pDoc); // constructor --- 982,987 ---- *************** *** 1237,1242 **** --- 1237,1246 ---- long PenColour, long PenStyle, long PenWidth); long LoadImage (LPCTSTR ImageId, LPCTSTR FileName); + long LoadPngImage (LPCTSTR ImageId, LPCTSTR FileName); + + long Write (LPCTSTR FileName); + long WritePng (LPCTSTR FileName, const BITMAPINFO * bmi, unsigned char * pData); long DrawImage(LPCTSTR ImageId, long Left, long Top, long Right, long Bottom, *************** *** 1301,1306 **** --- 1305,1319 ---- long Filter(long Left, long Top, long Right, long Bottom, short Operation, double Options); + + long SetPixel(long x, long y, long Colour); + + long GetPixel(long x, long y); + + long MergeImageAlpha(LPCTSTR ImageId, LPCTSTR MaskId, + long Left, long Top, long Right, long Bottom, + short Mode, double Opacity, + long SrcLeft, long SrcTop, long SrcRight, long SrcBottom); }; Index: Utilities.cpp =================================================================== RCS file: /cvs/mushclient/Utilities.cpp,v retrieving revision 1.78 retrieving revision 1.79 diff -c -r1.78 -r1.79 *** Utilities.cpp 27 Jun 2008 21:35:50 -0000 1.78 --- Utilities.cpp 26 Aug 2008 05:23:14 -0000 1.79 *************** *** 8,15 **** --- 8,20 ---- #include "mainfrm.h" #include "color.h" + #include "errors.h" + #include "pcre_internal.h" + #define PNG_NO_CONSOLE_IO + #include "png.h" + #ifdef _DEBUG //#define new DEBUG_NEW #undef THIS_FILE *************** *** 2969,2972 **** --- 2974,3124 ---- { EnumWindows (&EnumWindowsProc, (int) name); } /* end of send_to_front */ + + + static void user_error_fn(png_structp png_ptr, + png_const_charp error_msg) + { + // AfxMessageBox (error_msg); + } + + static void user_warning_fn(png_structp png_ptr, + png_const_charp warning_msg) + { + // AfxMessageBox (warning_msg); + + } + + static int BytesPerLine (int nWidth, int nBitsPerPixel) + { + return ( (nWidth * nBitsPerPixel + 31) & (~31) ) / 8; + } + + long LoadPng (LPCTSTR FileName, HBITMAP & hbmp) // load a PNG file into a bitmap + { + // open file + FILE *fp = fopen(FileName, "rb"); + if (!fp) + return (eFileNotFound); + + unsigned char header [8]; + + // read signature + if (fread(header, 1, sizeof header, fp) != sizeof header) + { + fclose (fp); + return (eUnableToLoadImage); // file too small + } + + // check signature + if (png_sig_cmp(header, 0, sizeof header)) + { + fclose (fp); + return (eUnableToLoadImage); // bad signature + } + + // create PNG structure + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, NULL, + user_error_fn, user_warning_fn); + + if (!png_ptr) + { + fclose (fp); + return eUnableToLoadImage; + } + + // create info structure + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + fclose (fp); + return eUnableToLoadImage; + } + + // create end info structure + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + fclose (fp); + return eUnableToLoadImage; + } + + + // if png fails it will longjmp back to here, so we destroy the structure, + // close the file, and wrap up + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + fclose (fp); + return eUnableToLoadImage; + } + + + // initialize IO + png_init_io (png_ptr, fp); + + // tell it we have read the sig + png_set_sig_bytes(png_ptr, sizeof header); + + int png_transforms = PNG_TRANSFORM_STRIP_16 | // Strip 16-bit samples to 8 bits + PNG_TRANSFORM_STRIP_ALPHA | // Discard the alpha channel + PNG_TRANSFORM_PACKING | // Expand 1, 2 and 4-bit samples to bytes + PNG_TRANSFORM_BGR; // Flip RGB to BGR, RGBA to BGRA + + // read the file + png_read_png(png_ptr, info_ptr, png_transforms, NULL); + + // note: png_read_end not needed with png_read_png (done already) + + // get the row pointers + png_bytep * row_pointers = png_get_rows(png_ptr, info_ptr); + + // make a bitmap + CDC B_DC; + B_DC.CreateCompatibleDC (NULL); + CBitmap B_bmp; + + BITMAPINFO bmiB; + ZeroMemory (&bmiB, sizeof bmiB); + + long bpl = BytesPerLine (info_ptr->width, 24); + + bmiB.bmiHeader.biSize = sizeof bmiB; + bmiB.bmiHeader.biWidth = info_ptr->width; + bmiB.bmiHeader.biHeight = info_ptr->height; + bmiB.bmiHeader.biPlanes = 1; + bmiB.bmiHeader.biBitCount = 24; + bmiB.bmiHeader.biCompression = BI_RGB; + bmiB.bmiHeader.biSizeImage = info_ptr->height * bpl; + + unsigned char * pB = NULL; + + hbmp = CreateDIBSection(NULL, &bmiB, DIB_RGB_COLORS, (void**) &pB, NULL, 0); + + if (!hbmp) + return eUnableToLoadImage; + + long row; + unsigned char * p = pB; + + // have to reverse row order + for (row = 0; row < info_ptr->height; row++, p += bpl) + memcpy (p, row_pointers [info_ptr->height - row - 1], bpl); + + // done with data + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + + // done with file + fclose(fp); + + return eOK; + } // end of LoadPng + + Index: doc.cpp =================================================================== RCS file: /cvs/mushclient/doc.cpp,v retrieving revision 1.255 retrieving revision 1.257 diff -c -r1.255 -r1.257 *** doc.cpp 5 Aug 2008 06:25:12 -0000 1.255 --- doc.cpp 26 Aug 2008 05:23:14 -0000 1.257 *************** *** 548,553 **** --- 548,559 ---- DISP_FUNCTION(CMUSHclientDoc, "TextRectangle", TextRectangle, VT_I4, VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4) DISP_FUNCTION(CMUSHclientDoc, "WindowGradient", WindowGradient, VT_I4, VTS_BSTR VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I2) DISP_FUNCTION(CMUSHclientDoc, "WindowFilter", WindowFilter, VT_I4, VTS_BSTR VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I2 VTS_R8) + DISP_FUNCTION(CMUSHclientDoc, "WindowSetPixel", WindowSetPixel, VT_I4, VTS_BSTR VTS_I4 VTS_I4 VTS_I4) + DISP_FUNCTION(CMUSHclientDoc, "WindowGetPixel", WindowGetPixel, VT_I4, VTS_BSTR VTS_I4 VTS_I4) + DISP_FUNCTION(CMUSHclientDoc, "WindowWrite", WindowWrite, VT_I4, VTS_BSTR VTS_BSTR) + DISP_FUNCTION(CMUSHclientDoc, "FilterPixel", FilterPixel, VT_I4, VTS_I4 VTS_I2 VTS_R8) + DISP_FUNCTION(CMUSHclientDoc, "BlendPixel", BlendPixel, VT_I4, VTS_I4 VTS_I4 VTS_I2 VTS_R8) + DISP_FUNCTION(CMUSHclientDoc, "WindowMergeImageAlpha", WindowMergeImageAlpha, VT_I4, VTS_BSTR VTS_BSTR VTS_BSTR VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I2 VTS_R8 VTS_I4 VTS_I4 VTS_I4 VTS_I4) DISP_PROPERTY_PARAM(CMUSHclientDoc, "NormalColour", GetNormalColour, SetNormalColour, VT_I4, VTS_I2) DISP_PROPERTY_PARAM(CMUSHclientDoc, "BoldColour", GetBoldColour, SetBoldColour, VT_I4, VTS_I2) DISP_PROPERTY_PARAM(CMUSHclientDoc, "CustomColourText", GetCustomColourText, SetCustomColourText, VT_I4, VTS_I2) *************** *** 4960,4965 **** --- 4966,4975 ---- void CMUSHclientDoc::ClearOutput (void) { + + if (m_pLinePositions == NULL) + return; + POSITION pos; // delete lines list *************** *** 7936,7939 **** --- 7946,7951 ---- m_strSpecialFontName.Empty (); } + + Index: doc.h =================================================================== RCS file: /cvs/mushclient/doc.h,v retrieving revision 1.271 retrieving revision 1.274 diff -c -r1.271 -r1.274 *** doc.h 5 Aug 2008 06:25:12 -0000 1.271 --- doc.h 26 Aug 2008 05:23:14 -0000 1.274 *************** *** 21,28 **** // New versions - things to change ! #define THISVERSION 435 // Step 1. ! const CString MUSHCLIENT_VERSION = "4.35"; // Step 2. // Step 3. Don't forget VERSION resource in Resources tab // Step 4. Remember: README.TXT --- 21,28 ---- // New versions - things to change ! #define THISVERSION 436 // Step 1. ! const CString MUSHCLIENT_VERSION = "4.36"; // Step 2. // Step 3. Don't forget VERSION resource in Resources tab // Step 4. Remember: README.TXT *************** *** 2506,2511 **** --- 2506,2517 ---- afx_msg long TextRectangle(long Left, long Top, long Right, long Bottom, long BorderOffset, long BorderColour, long BorderWidth, long OutsideFillColour, long OutsideFillStyle); afx_msg long WindowGradient(LPCTSTR Name, long Left, long Top, long Right, long Bottom, long StartColour, long EndColour, short Mode); afx_msg long WindowFilter(LPCTSTR Name, long Left, long Top, long Right, long Bottom, short Operation, double Options); + afx_msg long WindowSetPixel(LPCTSTR Name, long x, long y, long Colour); + afx_msg long WindowGetPixel(LPCTSTR Name, long x, long y); + afx_msg long WindowWrite(LPCTSTR Name, LPCTSTR FileName); + afx_msg long FilterPixel(long Pixel, short Operation, double Options); + afx_msg long BlendPixel(long Blend, long Base, short Mode, double Opacity); + afx_msg long WindowMergeImageAlpha(LPCTSTR Name, LPCTSTR ImageId, LPCTSTR MaskId, long Left, long Top, long Right, long Bottom, short Mode, double Opacity, long SrcLeft, long SrcTop, long SrcRight, long SrcBottom); afx_msg long GetNormalColour(short WhichColour); afx_msg void SetNormalColour(short WhichColour, long nNewValue); afx_msg long GetBoldColour(short WhichColour); Index: functionlist.cpp =================================================================== RCS file: /cvs/mushclient/functionlist.cpp,v retrieving revision 1.53 retrieving revision 1.55 diff -c -r1.53 -r1.55 *** functionlist.cpp 2 Aug 2008 06:35:23 -0000 1.53 --- functionlist.cpp 26 Aug 2008 05:23:14 -0000 1.55 *************** *** 49,55 **** "ArraySet", "ArraySize", "Base64Decode", ! "Base64Encode", "BoldColour", "BroadcastPlugin", "CallPlugin", --- 49,56 ---- "ArraySet", "ArraySize", "Base64Decode", ! "Base64Encode", ! "BlendPixel", "BoldColour", "BroadcastPlugin", "CallPlugin", *************** *** 123,128 **** --- 124,130 ---- "EvaluateSpeedwalk", "Execute", "ExportXML", + "FilterPixel", "FixupEscapeSequences", "FixupHTML", "FlushLog", *************** *** 358,363 **** --- 360,366 ---- "WindowFont", "WindowFontInfo", "WindowFontList", + "WindowGetPixel", "WindowHotspotInfo", "WindowHotspotList", "WindowImageFromWindow", *************** *** 368,379 **** --- 371,385 ---- "WindowLine", "WindowList", "WindowLoadImage", + "WindowMergeImageAlpha", "WindowPolygon", "WindowPosition", "WindowRectOp", + "WindowSetPixel", "WindowShow", "WindowText", "WindowTextWidth", + "WindowWrite", "WorldAddress", "WorldName", "WorldPort", Index: lua_methods.cpp =================================================================== RCS file: /cvs/mushclient/lua_methods.cpp,v retrieving revision 1.112 retrieving revision 1.114 diff -c -r1.112 -r1.114 *** lua_methods.cpp 2 Aug 2008 06:35:23 -0000 1.112 --- lua_methods.cpp 26 Aug 2008 05:23:14 -0000 1.114 *************** *** 912,917 **** --- 912,931 ---- return pushVariant (L, v); } // end of L_Base64Encode + //---------------------------------------- + // world.BlendPixel + //---------------------------------------- + static int L_BlendPixel (lua_State *L) + { + CMUSHclientDoc *pDoc = doc (L); + lua_pushnumber (L, pDoc->BlendPixel ( + my_checknumber (L, 1), // Blend + my_checknumber (L, 2), // Base + my_checknumber (L, 3), // Mode + my_optnumber (L, 4, 1) // Opacity + )); + return 1; // number of result fields + } // end of L_BlendPixel //---------------------------------------- // world.GetBoldColour *************** *** 1857,1862 **** --- 1871,1890 ---- //---------------------------------------- + // world.FilterPixel + //---------------------------------------- + static int L_FilterPixel (lua_State *L) + { + CMUSHclientDoc *pDoc = doc (L); + lua_pushnumber (L, pDoc->FilterPixel ( + my_checknumber (L, 1), // Pixel + my_checknumber (L, 2), // Operation + my_checknumber (L, 3) // Options + )); + return 1; // number of result fields + } // end of L_FilterPixel + + //---------------------------------------- // world.FixupEscapeSequences //---------------------------------------- static int L_FixupEscapeSequences (lua_State *L) *************** *** 5047,5053 **** return 1; // number of result fields } // end of L_WindowBlendImage - //---------------------------------------- // world.WindowCircleOp //---------------------------------------- --- 5075,5080 ---- *************** *** 5229,5234 **** --- 5256,5275 ---- } // end of L_WindowFontList //---------------------------------------- + // world.WindowGetPixel + //---------------------------------------- + static int L_WindowGetPixel (lua_State *L) + { + CMUSHclientDoc *pDoc = doc (L); + lua_pushnumber (L, pDoc->WindowGetPixel ( + my_checkstring (L, 1), // Name + my_checknumber (L, 2), // x + my_checknumber (L, 3) // y + )); + return 1; // number of result fields + } // end of L_WindowGetPixel + + //---------------------------------------- // world.WindowGradient //---------------------------------------- static int L_WindowGradient (lua_State *L) *************** *** 5394,5399 **** --- 5435,5465 ---- } // end of L_WindowLoadImage //---------------------------------------- + // world.WindowMergeImageAlpha + //---------------------------------------- + static int L_WindowMergeImageAlpha (lua_State *L) + { + CMUSHclientDoc *pDoc = doc (L); + lua_pushnumber (L, pDoc->WindowMergeImageAlpha ( + my_checkstring (L, 1), // Name + my_checkstring (L, 2), // ImageId + my_checkstring (L, 3), // MaskId + my_checknumber (L, 4), // Left + my_checknumber (L, 5), // Top + my_checknumber (L, 6), // Right + my_checknumber (L, 7), // Bottom + my_checknumber (L, 8), // Mode + my_optnumber (L, 9, 1), // Opacity + my_optnumber (L, 10, 0), // SrcLeft + my_optnumber (L, 11, 0), // SrcTop + my_optnumber (L, 12, 0), // SrcRight + my_optnumber (L, 13, 0) // SrcBottom + )); + return 1; // number of result fields + } // end of L_WindowMergeImageAlpha + + + //---------------------------------------- // world.WindowPolygon //---------------------------------------- static int L_WindowPolygon (lua_State *L) *************** *** 5450,5455 **** --- 5516,5536 ---- } // end of L_WindowRectOp //---------------------------------------- + // world.WindowSetPixel + //---------------------------------------- + static int L_WindowSetPixel (lua_State *L) + { + CMUSHclientDoc *pDoc = doc (L); + lua_pushnumber (L, pDoc->WindowSetPixel ( + my_checkstring (L, 1), // Name + my_checknumber (L, 2), // x + my_checknumber (L, 3), // y + my_checknumber (L, 4) // Colour + )); + return 1; // number of result fields + } // end of L_WindowSetPixel + + //---------------------------------------- // world.WindowShow //---------------------------------------- static int L_WindowShow (lua_State *L) *************** *** 5499,5504 **** --- 5580,5599 ---- } // end of WindowTextWidth //---------------------------------------- + // world.WindowWrite + //---------------------------------------- + static int L_WindowWrite (lua_State *L) + { + CMUSHclientDoc *pDoc = doc (L); + lua_pushnumber (L, pDoc->WindowWrite ( + my_checkstring (L, 1), // Name + my_checkstring (L, 2) // FileName + )); + + return 1; // number of result fields + } // end of L_WindowWrite + + //---------------------------------------- // world.WorldAddress //---------------------------------------- static int L_WorldAddress (lua_State *L) *************** *** 5584,5589 **** --- 5679,5685 ---- {"ArraySize", L_ArraySize}, {"Base64Decode", L_Base64Decode}, {"Base64Encode", L_Base64Encode}, + {"BlendPixel", L_BlendPixel}, {"GetBoldColour", L_GetBoldColour}, {"SetBoldColour", L_SetBoldColour}, {"BroadcastPlugin", L_BroadcastPlugin}, *************** *** 5661,5666 **** --- 5757,5763 ---- {"EvaluateSpeedwalk", L_EvaluateSpeedwalk}, {"Execute", L_Execute}, {"ExportXML", L_ExportXML}, + {"FilterPixel", L_FilterPixel}, {"FixupEscapeSequences", L_FixupEscapeSequences}, {"FixupHTML", L_FixupHTML}, {"FlushLog", L_FlushLog}, *************** *** 5905,5910 **** --- 6002,6008 ---- {"WindowFont", L_WindowFont}, {"WindowFontInfo", L_WindowFontInfo}, {"WindowFontList", L_WindowFontList}, + {"WindowGetPixel", L_WindowGetPixel}, {"WindowGradient", L_WindowGradient}, {"WindowHotspotInfo", L_WindowHotspotInfo}, {"WindowHotspotList", L_WindowHotspotList}, *************** *** 5916,5927 **** --- 6014,6028 ---- {"WindowLine", L_WindowLine}, {"WindowList", L_WindowList}, {"WindowLoadImage", L_WindowLoadImage}, + {"WindowMergeImageAlpha", L_WindowMergeImageAlpha}, {"WindowPolygon", L_WindowPolygon}, {"WindowPosition", L_WindowPosition}, {"WindowRectOp", L_WindowRectOp}, + {"WindowSetPixel", L_WindowSetPixel}, {"WindowShow", L_WindowShow}, {"WindowText", L_WindowText}, {"WindowTextWidth", L_WindowTextWidth}, + {"WindowWrite", L_WindowWrite}, {"WorldAddress", L_WorldAddress}, {"WorldName", L_WorldName}, {"WorldPort", L_WorldPort}, Index: methods.cpp =================================================================== RCS file: /cvs/mushclient/methods.cpp,v retrieving revision 1.248 retrieving revision 1.252 diff -c -r1.248 -r1.252 *** methods.cpp 5 Aug 2008 06:25:12 -0000 1.248 --- methods.cpp 26 Aug 2008 05:23:14 -0000 1.252 *************** *** 26,31 **** --- 26,33 ---- #include #include "dmetaph.h" + #include "png.h" + #ifdef _DEBUG //#define new DEBUG_NEW #undef THIS_FILE *************** *** 4146,4151 **** --- 4148,4157 ---- { 77, "OS Version - service pack" }, { 78, "Foreground image filename" }, { 79, "Background image filename" }, + { 80, "LibPNG version number" }, + { 81, "LibPNG header version string" }, + + // (booleans - calculated at runtime) *************** *** 4250,4255 **** --- 4256,4263 ---- { 277, "Text rectangle - border width" }, { 278, "Text rectangle - outside colour" }, { 279, "Text rectangle - outside style" }, + { 280, "Output window client height" }, + { 281, "Output window client width" }, *************** *** 4452,4457 **** --- 4460,4467 ---- case 78: SetUpVariantString (vaResult, m_strForegroundImageName); break; case 79: SetUpVariantString (vaResult, m_strBackgroundImageName); break; + case 80: SetUpVariantString (vaResult, PNG_LIBPNG_VER_STRING); break; + case 81: SetUpVariantString (vaResult, PNG_HEADER_VERSION_STRING); break; case 101: SetUpVariantBool (vaResult, m_bNoEcho); break; case 102: SetUpVariantBool (vaResult, m_bDebugIncomingPackets); break; *************** *** 4815,4820 **** --- 4825,4868 ---- case 278: SetUpVariantLong (vaResult, m_TextRectangleOutsideFillColour); break; case 279: SetUpVariantLong (vaResult, m_TextRectangleOutsideFillStyle); break; + case 280: + { + RECT rect; + for(POSITION pos = GetFirstViewPosition(); pos != NULL; ) + { + CView* pView = GetNextView(pos); + + if (pView->IsKindOf(RUNTIME_CLASS(CMUSHView))) + { + CMUSHView* pmyView = (CMUSHView*)pView; + pmyView->GetClientRect(&rect); + SetUpVariantLong (vaResult, rect.bottom); + break; + } // end of being a CMUSHView + } // end of loop through views + + } + break; + + case 281: + { + RECT rect; + for(POSITION pos = GetFirstViewPosition(); pos != NULL; ) + { + CView* pView = GetNextView(pos); + + if (pView->IsKindOf(RUNTIME_CLASS(CMUSHView))) + { + CMUSHView* pmyView = (CMUSHView*)pView; + pmyView->GetClientRect(&rect); + SetUpVariantLong (vaResult, rect.right); + break; + } // end of being a CMUSHView + } // end of loop through views + + } + break; + case 301: if (m_tConnectTime.GetTime ()) // only if non-zero, otherwise return empty SetUpVariantDate (vaResult, COleDateTime (m_tConnectTime.GetTime ())); *************** *** 12376,12393 **** UpdateAllViews (NULL); ! // no file name means get rid of images ! if (strlen (FileName) == 0) return eOK; ! HBITMAP hBmp = (HBITMAP)::LoadImage( ! NULL, ! FileName, ! IMAGE_BITMAP, ! 0, ! 0, ! LR_LOADFROMFILE|LR_CREATEDIBSECTION ! ); if (hBmp) { --- 12424,12469 ---- UpdateAllViews (NULL); ! CString strFileName = FileName; ! ! strFileName.TrimLeft (); ! strFileName.TrimRight (); ! ! // no file name means get rid of image ! if (strFileName.IsEmpty ()) return eOK; ! // have to be long enough to have x.bmp ! if (strFileName.GetLength () < 5) ! return eBadParameter; ! ! HBITMAP hBmp; ! ! // handle PNG files separately ! if (strFileName.Right (4).CompareNoCase (".png") == 0) ! { ! long result = LoadPng (FileName, hBmp); ! ! if (result != eOK) ! return result; ! ! } // png file ! else ! { ! ! // must be .bmp or .png file ! if (strFileName.Right (4).CompareNoCase (".bmp") != 0) ! return eBadParameter; ! ! hBmp = (HBITMAP)::LoadImage( ! NULL, ! FileName, ! IMAGE_BITMAP, ! 0, ! 0, ! LR_LOADFROMFILE|LR_CREATEDIBSECTION ! ); ! } // bmp file if (hBmp) { *************** *** 12418,12435 **** UpdateAllViews (NULL); ! // no file name means get rid of images ! if (strlen (FileName) == 0) return eOK; ! HBITMAP hBmp = (HBITMAP)::LoadImage( ! NULL, ! FileName, ! IMAGE_BITMAP, ! 0, ! 0, ! LR_LOADFROMFILE|LR_CREATEDIBSECTION ! ); if (hBmp) { --- 12494,12539 ---- UpdateAllViews (NULL); ! CString strFileName = FileName; ! ! strFileName.TrimLeft (); ! strFileName.TrimRight (); ! ! // no file name means get rid of image ! if (strFileName.IsEmpty ()) return eOK; ! // have to be long enough to have x.bmp ! if (strFileName.GetLength () < 5) ! return eBadParameter; ! ! HBITMAP hBmp; ! ! // handle PNG files separately ! if (strFileName.Right (4).CompareNoCase (".png") == 0) ! { ! long result = LoadPng (FileName, hBmp); ! ! if (result != eOK) ! return result; ! ! } // png file ! else ! { ! ! // must be .bmp or .png file ! if (strFileName.Right (4).CompareNoCase (".bmp") != 0) ! return eBadParameter; ! ! hBmp = (HBITMAP)::LoadImage( ! NULL, ! FileName, ! IMAGE_BITMAP, ! 0, ! 0, ! LR_LOADFROMFILE|LR_CREATEDIBSECTION ! ); ! } // bmp file if (hBmp) { *************** *** 12752,12757 **** --- 12856,12872 ---- return it->second->LoadImage (ImageId, FileName); } // end of CMUSHclientDoc::WindowLoadImage + long CMUSHclientDoc::WindowWrite(LPCTSTR Name, LPCTSTR FileName) + { + MiniWindowMapIterator it = m_MiniWindows.find (Name); + + if (it == m_MiniWindows.end ()) + return eNoSuchWindow; + + return it->second->Write (FileName); + } // CMUSHclientDoc::WindowWrite + + // draw an image long CMUSHclientDoc::WindowDrawImage(LPCTSTR Name, LPCTSTR ImageId, *************** *** 13017,13023 **** if (it == m_MiniWindows.end ()) return vaResult; ! it->second->FontInfo (HotspotId, InfoType, vaResult); return vaResult; } // end of CMUSHclientDoc::WindowHotspotInfo --- 13132,13138 ---- if (it == m_MiniWindows.end ()) return vaResult; ! it->second->HotspotInfo (HotspotId, InfoType, vaResult); return vaResult; } // end of CMUSHclientDoc::WindowHotspotInfo *************** *** 13125,13130 **** --- 13240,13259 ---- m_TextRectangleOutsideFillColour = OutsideFillColour; m_TextRectangleOutsideFillStyle = OutsideFillStyle; + // refresh views - get scroll bars right + + for(POSITION pos=GetFirstViewPosition();pos!=NULL;) + { + CView* pView = GetNextView(pos); + + if (pView->IsKindOf(RUNTIME_CLASS(CMUSHView))) + { + CMUSHView* pmyView = (CMUSHView*)pView; + + pmyView->addedstuff(); + } + } + Redraw (); return eOK; } // end of CMUSHclientDoc::TextRectangle *************** *** 13159,13164 **** --- 13288,13816 ---- Operation, Options); } // CMUSHclientDoc::WindowFilter + + long CMUSHclientDoc::WindowSetPixel(LPCTSTR Name, long x, long y, long Colour) + { + MiniWindowMapIterator it = m_MiniWindows.find (Name); + + if (it == m_MiniWindows.end ()) + return eNoSuchWindow; + + return it->second->SetPixel (x, y, Colour); + } // end of CMUSHclientDoc::WindowSetPixel + + + long CMUSHclientDoc::WindowGetPixel(LPCTSTR Name, long x, long y) + { + MiniWindowMapIterator it = m_MiniWindows.find (Name); + + if (it == m_MiniWindows.end ()) + return -2; + + return it->second->GetPixel (x, y); + } // end of CMUSHclientDoc::WindowGetPixel + + + // see also: CMiniWindow::Filter + + long CMUSHclientDoc::FilterPixel(long Pixel, short Operation, double Options) + { + long r = GetRValue (Pixel), + g = GetGValue (Pixel), + b = GetBValue (Pixel); + + switch (Operation) + { + case 1: // Noise + { + double threshold = Options / 100.0; + r += (128 - genrand () * 256) * threshold; + g += (128 - genrand () * 256) * threshold; + b += (128 - genrand () * 256) * threshold; + break; + } + + case 2: // MonoNoise + { + double threshold = Options / 100.0; + long j = (128 - genrand () * 256) * threshold; + r += j; + g += j; + b += j; + break; + } + + + case 7: // Brightness + { + r += Options; + g += Options; + b += Options; + break; + } + + + case 8: // Contrast + { + double c; + + c = r - 128; // center on zero + c *= Options; // multiply by contrast + r = c + 128; // put back + + c = g - 128; // center on zero + c *= Options; // multiply by contrast + g = c + 128; // put back + + c = b - 128; // center on zero + c *= Options; // multiply by contrast + b = c + 128; // put back + + break; + } + + + case 9: // Gamma + { + double c; + + if (Options < 0.0) + Options = 0.0; + + c = ( (double) r) / 255.0; // normalize it + c = pow (c, Options); + r = c * 255.0; + + c = ( (double) g) / 255.0; // normalize it + c = pow (c, Options); + g = c * 255.0; + + c = ( (double) b) / 255.0; // normalize it + c = pow (c, Options); + b = c * 255.0; + + break; + } + + case 10: // ColourBrightness - red + { + r += Options; + break; + } + + case 11: // ColourContrast - red + { + double c; + + c = r - 128; // center on zero + c *= Options; // multiply by contrast + r = c + 128; // put back + + break; + } + + case 12: // ColourGamma - red + { + double c; + + if (Options < 0.0) + Options = 0.0; + + c = ( (double) r) / 255.0; // normalize it + c = pow (c, Options); + r = c * 255.0; + + break; + } + + case 13: // ColourBrightness - green + { + g += Options; + break; + } + + case 14: // ColourContrast - green + { + double c; + + c = g - 128; // center on zero + c *= Options; // multiply by contrast + g = c + 128; // put back + + break; + } + + case 15: // ColourGamma - green + { + double c; + + if (Options < 0.0) + Options = 0.0; + + c = ( (double) g) / 255.0; // normalize it + c = pow (c, Options); + g = c * 255.0; + + break; + } + + case 16: // ColourBrightness - blue + { + b += Options; + break; + } + + case 17: // ColourContrast - blue + { + double c; + + c = b - 128; // center on zero + c *= Options; // multiply by contrast + b = c + 128; // put back + + break; + } + + case 18: // ColourGamma - blue + { + double c; + + if (Options < 0.0) + Options = 0.0; + + c = ( (double) b) / 255.0; // normalize it + c = pow (c, Options); + b = c * 255.0; + + break; + } + + case 19: // MakeGreyscale - linear + { + double c; + c = r + g + b; + c /= 3; + r = c; + g = c; + b = c; + break; + } + + case 20: // MakeGreyscale - perceptual + { + double c; + c = b * 0.11 + // blue (perceptual) + g * 0.59 + // green + r * 0.30; // red + c /= 3; + r = c; + g = c; + b = c; + break; + } + + case 21: // Brightness - multiplicative + { + r *= Options; + g *= Options; + b *= Options; + break; + } + + case 22: // Brightness - multiplicative - red + { + r *= Options; + break; + } + + case 23: // Brightness - multiplicative - green + { + g *= Options; + break; + } + + case 24: // Brightness - multiplicative - blue + { + b *= Options; + break; + } + + + case 27: // Average (of 1 pixel is itself) + break; + + default: return -1; + + } // end of switch + + + return RGB (CLAMP (r), CLAMP (g), CLAMP (b)); + } // end of CMUSHclientDoc::FilterPixel + + #define Blend_It(Op) \ + do \ + if (Opacity < 1.0) \ + { \ + r = Blend_Opacity (rA, rB, Op, Opacity);\ + g = Blend_Opacity (gA, gB, Op, Opacity);\ + b = Blend_Opacity (bA, bB, Op, Opacity);\ + } \ + else\ + { \ + r = Op (rA, rB);\ + g = Op (gA, gB);\ + b = Op (bA, bB);\ + } \ + while (false) + + + #define Colour_Op(fR,fG,fB) \ + do \ + { \ + if (Opacity < 1.0) \ + { \ + r = Simple_Opacity (rB, fR, Opacity); \ + g = Simple_Opacity (gB, fG, Opacity); \ + b = Simple_Opacity (bB, fB, Opacity); \ + }\ + else\ + {\ + r = fR; \ + g = fG; \ + b = fB; \ + }\ + }\ + while (false) + + + // see also: CMiniWindow::BlendImage + + long CMUSHclientDoc::BlendPixel(long Blend, long Base, short Mode, double Opacity) + { + long rA = GetRValue (Blend), + gA = GetGValue (Blend), + bA = GetBValue (Blend); + long rB = GetRValue (Base), + gB = GetGValue (Base), + bB = GetBValue (Base); + + long r, g, b; + + if (Opacity < 0.0 || Opacity > 1.0) + return -2; + + // precompute cos table + static unsigned char cos_table [256]; + static bool bTableComputed = false; + + if (!bTableComputed) + { + double pi_div255 = 3.1415926535898 / 255.0; + long i; + for (i = 0; i < 256; i++) + { + double a = 64.0 - cos ((double) i * pi_div255) * 64.0; + cos_table [i] = (uint8) (a + 0.5); // round + } + bTableComputed = true; + } // table needs computing + + switch (Mode) + { + + // normal modes + case 1: Blend_It (Blend_Normal); break; + case 2: Blend_It (Blend_Average); break; + case 3: Blend_It (Blend_Interpolate); break; + + case 4: // dissolve - randomly choose pixels based on opacity + r = (genrand () < Opacity) ? rA : rB; + g = (genrand () < Opacity) ? gA : gB; + b = (genrand () < Opacity) ? bA : bB; + break; + + + // darkening modes + case 5: Blend_It (Blend_Darken); break; + case 6: Blend_It (Blend_Multiply); break; + case 7: Blend_It (Blend_ColorBurn); break; + case 8: Blend_It (Blend_LinearBurn); break; + case 9: Blend_It (Blend_InverseColorBurn); break; + case 10: Blend_It (Blend_Subtract); break; + + // lightening modes + case 11: Blend_It (Blend_Lighten); break; + case 12: Blend_It (Blend_Screen); break; + case 13: Blend_It (Blend_ColorDodge); break; + case 14: Blend_It (Blend_LinearDodge);break; + case 15: Blend_It (Blend_InverseColorDodge); break; + case 16: Blend_It (Blend_Add); break; + + // soft/hard light etc. + case 17: Blend_It (Blend_Overlay); break; + case 18: Blend_It (Blend_SoftLight); break; + case 19: Blend_It (Blend_HardLight); break; + case 20: Blend_It (Blend_VividLight); break; + case 21: Blend_It (Blend_LinearLight);break; + case 22: Blend_It (Blend_PinLight); break; + case 23: Blend_It (Blend_HardMix); break; + + // difference modes + case 24: Blend_It (Blend_Difference); break; + case 25: Blend_It (Blend_Exclusion); break; + + // glow modes + case 26: Blend_It (Blend_Reflect); break; + case 27: Blend_It (Blend_Glow); break; + case 28: Blend_It (Blend_Freeze); break; + case 29: Blend_It (Blend_Heat); break; + + case 30: Blend_It (Blend_Negation); break; + case 31: Blend_It (Blend_Phoenix); break; + case 32: Blend_It (Blend_Stamp); break; + + // logical modes + case 33: Blend_It (Blend_Xor); break; + case 34: Blend_It (Blend_And); break; + case 35: Blend_It (Blend_Or); break; + + // the follow modes take one colour from the blend and retain 2 from the base + case 36: Colour_Op (rA, gB, bB); break; // red + case 37: Colour_Op (rB, gA, bB); break; // green + case 38: Colour_Op (rB, gB, bA); break; // blue + + // the follow modes take two colours from the blend and retain 1 from the base + case 39: Colour_Op (rA, gA, bB); break; // yellow + case 40: Colour_Op (rB, gA, bA); break; // cyan + case 41: Colour_Op (rA, gB, bA); break; // magenta + + // limit green + case 42: Colour_Op (rA, (gA > rA) ? rA : gA, bA); break; // green limited by red + case 43: Colour_Op (rA, (gA > bA) ? bA : gA, bA); break; // green limited by blue + case 44: Colour_Op (rA, (gA > ((rA + bA) / 2)) ? ((rA + bA) / 2) : gA, bA); break; // green limited by average of red and blue + + // limit blue + case 45: Colour_Op (rA, gA, (bA > rA) ? rA : bA); break; // blue limited by red + case 46: Colour_Op (rA, gA, (bA > gA) ? gA : bA); break; // blue limited by green + case 47: Colour_Op (rA, gA, (bA > ((rA + gA) / 2)) ? ((rA + gA) / 2) : bA); break; // blue limited by average of red and green + + // limit red + case 48: Colour_Op ((rA > gA) ? gA : rA, gA, bA); break; // red limited by green + case 49: Colour_Op ((rA > bA) ? bA : rA, gA, bA); break; // red limited by blue + case 50: Colour_Op ((rA > ((gA + bA) / 2)) ? ((gA + bA) / 2) : rA, gA, bA); break; // red limited by average of green and blue + + // select single colour + case 51: Colour_Op (rA, 0, 0); break; // red only (looks red) + case 52: Colour_Op (0, gA, 0); break; // green only (looks green) + case 53: Colour_Op (0, 0, bA); break; // blue only (looks blue) + + // discard single colour + case 54: Colour_Op (0, gA, bA); break; // discard red (looks cyan) + case 55: Colour_Op (rA, 0, bA); break; // discard green (looks magenta) + case 56: Colour_Op (rA, gA, 0); break; // discard blue (looks yellow) + + // one colour to all channels (ie. it looks grey) + case 57: Colour_Op (rA, rA, rA); break; // all red + case 58: Colour_Op (gA, gA, gA); break; // all green + case 59: Colour_Op (bA, bA, bA); break; // all blue + + case 60: // Hue mode + { + CColor cA, cB; // A = blend, B = base + + cA.SetRGB (rA, gA, bA); + cB.SetRGB (rB, gB, bB); + + cB.SetHue (cA.GetHue ()); // hue of blend image, others from base image + r = Simple_Opacity (rB, cB.GetRed (), Opacity); + g = Simple_Opacity (gB, cB.GetGreen (), Opacity); + b = Simple_Opacity (bB, cB.GetBlue (), Opacity); + } + break; + + case 61: // Saturation mode + { + CColor cA, cB; // A = blend, B = base + + cA.SetRGB (rA, gA, bA); + cB.SetRGB (rB, gB, bB); + + cB.SetSaturation (cA.GetSaturation ()); // saturation of blend image, others from base image + r = Simple_Opacity (rB, cB.GetRed (), Opacity); + g = Simple_Opacity (gB, cB.GetGreen (), Opacity); + b = Simple_Opacity (bB, cB.GetBlue (), Opacity); + } + break; + + case 62: // Colour mode + { + CColor cA, cB; // A = blend, B = base + + cA.SetRGB (rA, gA, bA); + cB.SetRGB (rB, gB, bB); + + cB.SetHue (cA.GetHue ()); // hue of blend image, + cB.SetSaturation (cA.GetSaturation ()); // saturation of blend image, luminance from base image + r = Simple_Opacity (rB, cB.GetRed (), Opacity); + g = Simple_Opacity (gB, cB.GetGreen (), Opacity); + b = Simple_Opacity (bB, cB.GetBlue (), Opacity); + } + break; + + + case 63: // Luminance mode + { + CColor cA, cB; // A = blend, B = base + + cA.SetRGB (rA, gA, bA); + cB.SetRGB (rB, gB, bB); + + cB.SetLuminance (cA.GetLuminance ()); // luminance from blend image, others from base image + + r = Simple_Opacity (rB, cB.GetRed (), Opacity); + g = Simple_Opacity (gB, cB.GetGreen (), Opacity); + b = Simple_Opacity (bB, cB.GetBlue (), Opacity); + + } + break; + + case 64: // HSL (hue to red, saturation to green, luminance to blue) + { + CColor cA, cB; // A = blend, B = base + cA.SetRGB (rA, gA, bA); + + r = Simple_Opacity (rB, cB.GetRed (), Opacity); + g = Simple_Opacity (gB, cB.GetGreen (), Opacity); + b = Simple_Opacity (bB, cB.GetBlue (), Opacity); + + } + break; + + default: return -1; + + } // end of switch + + + return RGB (CLAMP (r), CLAMP (g), CLAMP (b)); + } // end of CMUSHclientDoc::BlendPixel + + + long CMUSHclientDoc::WindowMergeImageAlpha(LPCTSTR Name, + LPCTSTR ImageId, LPCTSTR MaskId, + long Left, long Top, long Right, long Bottom, + short Mode, + double Opacity, + long SrcLeft, long SrcTop, long SrcRight, long SrcBottom) + { + MiniWindowMapIterator it = m_MiniWindows.find (Name); + + if (it == m_MiniWindows.end ()) + return eNoSuchWindow; + + return it->second->MergeImageAlpha (ImageId, MaskId, Left, Top, Right, Bottom, Mode, Opacity, SrcLeft, SrcTop, SrcRight, SrcBottom); + } // CMUSHclientDoc::WindowMergeImageAlpha + + /* Index: miniwindow.cpp =================================================================== RCS file: /cvs/mushclient/miniwindow.cpp,v retrieving revision 1.28 retrieving revision 1.33 diff -c -r1.28 -r1.33 *** miniwindow.cpp 6 Aug 2008 00:05:38 -0000 1.28 --- miniwindow.cpp 29 Aug 2008 03:33:41 -0000 1.33 *************** *** 8,13 **** --- 8,15 ---- #include "errors.h" #include "color.h" + #define PNG_NO_CONSOLE_IO + #include "png.h" // constructor CMiniWindow::CMiniWindow () : *************** *** 69,74 **** --- 71,81 ---- return Right; } // end CMiniWindow::FixRight + static int BytesPerLine (int nWidth, int nBitsPerPixel) + { + return ( (nWidth * nBitsPerPixel + 31) & (~31) ) / 8; + } + // a negative or zero value for the bottom of a rectange is considered offset from the bottom edge long CMiniWindow::FixBottom (const long Bottom) { *************** *** 937,946 **** m_Images.erase (it); } // no file name means get rid of image ! if (strlen (FileName) == 0) return eOK; HBITMAP hBmp = (HBITMAP)::LoadImage( NULL, FileName, --- 944,971 ---- m_Images.erase (it); } + CString strFileName = FileName; + + strFileName.TrimLeft (); + strFileName.TrimRight (); + // no file name means get rid of image ! if (strFileName.IsEmpty ()) return eOK; + // have to be long enough to have x.bmp + if (strFileName.GetLength () < 5) + return eBadParameter; + + // handle PNG files separately + if (strFileName.Right (4).CompareNoCase (".png") == 0) + return LoadPngImage (ImageId, FileName); + + // must be .bmp or .png file + if (strFileName.Right (4).CompareNoCase (".bmp") != 0) + return eBadParameter; + + HBITMAP hBmp = (HBITMAP)::LoadImage( NULL, FileName, *************** *** 968,973 **** --- 993,1209 ---- } // end of CMiniWindow::LoadImage + static void user_error_fn(png_structp png_ptr, + png_const_charp error_msg) + { + // AfxMessageBox (error_msg); + } + + static void user_warning_fn(png_structp png_ptr, + png_const_charp warning_msg) + { + // AfxMessageBox (warning_msg); + + } + + + long CMiniWindow::LoadPngImage (LPCTSTR ImageId, LPCTSTR FileName) + { + + HBITMAP hbmp; + + long result = LoadPng (FileName, hbmp); + + if (result != eOK) + return result; + + // make bitmap to add to images list + CBitmap * pImage = new CBitmap; + pImage->Attach (hbmp); + m_Images [ImageId] = pImage; + + return eOK; + } // end of CMiniWindow::LoadPngImage + + + + // saves an image file + long CMiniWindow::Write (LPCTSTR FileName) + { + + CString strFileName = FileName; + + strFileName.TrimLeft (); + strFileName.TrimRight (); + + if (strFileName.IsEmpty ()) + return eNoNameSpecified; + + // have to be long enough to have x.bmp + if (strFileName.GetLength () < 5) + return eBadParameter; + + // must be .bmp or .png file + if (strFileName.Right (4).CompareNoCase (".bmp") != 0 && + strFileName.Right (4).CompareNoCase (".png") != 0) + return eBadParameter; + + // get window data + CDC gDC; + gDC.CreateCompatibleDC(&dc); + CBitmap gbmp; + + BITMAPINFO bmi; + ZeroMemory (&bmi, sizeof bmi); + + bmi.bmiHeader.biSize = sizeof bmi; + bmi.bmiHeader.biWidth = m_iWidth; + bmi.bmiHeader.biHeight = m_iHeight; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 24; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = m_iHeight * BytesPerLine (m_iWidth, 24); + + unsigned char * pA = NULL; + + HBITMAP hbmG = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**) &pA, NULL, 0); + + HBITMAP hOldAbmp = (HBITMAP) SelectObject(gDC.m_hDC, hbmG); + + // copy image from miniwindow to bitmap + gDC.BitBlt (0, 0, m_iWidth, m_iHeight, &dc, 0, 0, SRCCOPY); + + long iReturn = eOK; + + // must be .bmp or .png file + if (strFileName.Right (4).CompareNoCase (".png") == 0) + iReturn = WritePng (FileName, &bmi, pA); + else + { // write BMP file + + // create requested file + CFile file; + if( !file.Open (FileName, CFile::modeWrite | CFile::modeCreate)) + return eCouldNotOpenFile; + + BITMAPFILEHEADER hdr; + ZeroMemory (&hdr, sizeof hdr); + + // Fill in the fields of the file header + hdr.bfType = ((WORD) ('M' << 8) | 'B'); // is always "BM" + hdr.bfOffBits = sizeof hdr + sizeof bmi.bmiHeader; + hdr.bfSize = hdr.bfOffBits + bmi.bmiHeader.biSizeImage; + + try + { + // Write the file header + file.Write( &hdr, sizeof hdr); + + // Write the bitmap info header + file.Write( &bmi.bmiHeader, sizeof bmi.bmiHeader); + + // Write the bits + file.Write( pA, bmi.bmiHeader.biSizeImage); + } + catch (CFileException * e) + { + e->Delete (); + iReturn = eLogFileBadWrite; + } // end of catching a file exception + + } // end of writing BMP file + + // finished with bitmap + SelectObject(gDC.m_hDC, hOldAbmp); + DeleteObject (hbmG); + + return iReturn; + + } // end of CMiniWindow::Write + + long CMiniWindow::WritePng (LPCTSTR FileName, const BITMAPINFO * bmi, unsigned char * pData) + { + // open file + FILE *fp = fopen(FileName, "wb"); + if (!fp) + return (eCouldNotOpenFile); + + // create PNG structure + png_structp png_ptr = png_create_write_struct + (PNG_LIBPNG_VER_STRING, NULL, + user_error_fn, user_warning_fn); + + if (!png_ptr) + { + fclose (fp); + return eLogFileBadWrite; + } + + // create info structure + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + fclose (fp); + return eLogFileBadWrite; + } + + + // if png fails it will longjmp back to here, so we destroy the structure, + // close the file, and wrap up + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose (fp); + return eLogFileBadWrite; + } + + // initialize IO + png_init_io (png_ptr, fp); + + // tell PNG the file format + png_set_IHDR (png_ptr, + info_ptr, + bmi->bmiHeader.biWidth, + bmi->bmiHeader.biHeight, + 8, // bits per pixel + PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + // set up pointer to each row of data + vector row_pointers; + row_pointers.resize (bmi->bmiHeader.biHeight); + + long bpl = BytesPerLine (bmi->bmiHeader.biWidth, 24); + + long row; + unsigned char * p = pData; + + // have to reverse row order + for (row = 0; row < info_ptr->height; row++, p += bpl) + row_pointers [bmi->bmiHeader.biHeight - row - 1] = p; + + // tell png where our pixel data is + png_set_rows (png_ptr, info_ptr, &row_pointers [0]); + + // write out the image data + png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_BGR, NULL); + + // wrap up + png_write_end (png_ptr, info_ptr); + + // done with data + png_destroy_write_struct (&png_ptr, &info_ptr); + + // done with file + fclose (fp); + + return eOK; + } // end of CMiniWindow::WritePng + + /* for monitors with 256 colours or less, consider: *************** *** 1022,1028 **** break; // straight copy case 2: dc.StretchBlt (Left, Top, FixRight (Right) - Left, FixBottom (Bottom) - Top, &bmDC, ! SrcLeft, SrcTop, SrcRight, SrcBottom, SRCCOPY); break; // stretch case 3: // transparency, och! --- 1258,1264 ---- break; // straight copy case 2: dc.StretchBlt (Left, Top, FixRight (Right) - Left, FixBottom (Bottom) - Top, &bmDC, ! SrcLeft, SrcTop, SrcRight - SrcLeft, SrcBottom - SrcTop, SRCCOPY); break; // stretch case 3: // transparency, och! *************** *** 1578,1630 **** // see: http://www.nathanm.com/photoshop-blending-math/ // and: http://www.pegtop.net/delphi/articles/blendmodes/ - #define uint8 unsigned char - #define sqr(x) ((x)*(x)) // square of x - - // A = blend, B = base - - #define Blend_Normal(A,B) ((uint8)(A)) - #define Blend_Lighten(A,B) ((uint8)((B > A) ? B:A)) - #define Blend_Darken(A,B) ((uint8)((B > A) ? A:B)) - #define Blend_Multiply(A,B) ((uint8)((A * B) / 255)) - #define Blend_Average(A,B) ((uint8)((A + B) / 2)) - #define Blend_Add(A,B) ((uint8)((A + B > 255) ? 255:(A + B))) - #define Blend_Subtract(A,B) ((uint8)((A + B < 255) ? 0:(A + B - 255))) - #define Blend_Difference(A,B) ((uint8)(abs(A - B))) - #define Blend_Negation(A,B) ((uint8)(255 - abs(255 - A - B))) - #define Blend_Screen(A,B) ((uint8)(255 - (((255 - A) * (255 - B)) >> 8))) - #define Blend_Exclusion(A,B) ((uint8)(A + B - 2 * A * B / 255)) - #define Blend_Overlay(A,B) ((uint8)((B < 128) ? (2 * A * B / 255):(255 - 2 * (255 - A) * (255 - B) / 255))) - #define Blend_SoftLight(A,B) ((uint8) ((A * B) >> 8) + ((B * (255 - (((255 - B) * (255-A)) >> 8) - ((A * B) >> 8) )) >> 8) ) // c = ((A * B) >> 8) - #define Blend_HardLight(A,B) (Blend_Overlay(B,A)) - #define Blend_ColorDodge(A,B) ((uint8)((A == 255) ? A:((B << 8 ) / (255 - A) > 255) ? 255:((B << 8 ) / (255 - A)))) - #define Blend_ColorBurn(A,B) ((uint8)((A == 0) ? 0:((255 - (((255 - B) << 8 ) / A)) < 0) ? 0:(255 - (((255 - B) << 8 ) / A)))) - #define Blend_LinearDodge(A,B) (Blend_Add(A,B)) - #define Blend_LinearBurn(A,B) (Blend_Subtract(A,B)) - #define Blend_LinearLight(A,B) ((uint8)(A < 128) ? Blend_LinearBurn((2 * A),B):Blend_LinearDodge((2 * (A - 128)),B)) - #define Blend_VividLight(A,B) ((uint8)(A < 128) ? Blend_ColorBurn((2 * A),B):Blend_ColorDodge((2 * (A - 128)),B)) - #define Blend_PinLight(A,B) ((uint8)(A < 128) ? Blend_Darken((2 * A),B):Blend_Lighten((2 *(A - 128)),B)) - #define Blend_HardMix(A,B) ((uint8)(A < 255 - B) ? 0:255) - #define Blend_Reflect(A,B) ((uint8)((B == 255) ? B:((A * A / (255 - B) > 255) ? 255:(A * A / (255 - B))))) - #define Blend_Glow(A,B) (Blend_Reflect(B,A)) - #define Blend_Phoenix(A,B) ((uint8)(min(A,B) - max(A,B) + 255)) - #define Blend_Opacity(A,B,F,O) ((uint8)(O * F(A,B) + (1 - O) * B)) - - #define Simple_Opacity(B,X,O) ((uint8)(O * X + (1 - O) * B)) - - #define Blend_InverseColorDodge(A,B) Blend_ColorDodge (B, A) - #define Blend_InverseColorBurn(A,B) Blend_ColorBurn (B, A) - #define Blend_Freeze(A,B) ((uint8)((A == 0) ? A:((255 - sqr(255 - B)/ A < 0) ? 0:(255 - sqr(255 - B) / A)))) - #define Blend_Heat(A,B) Blend_Freeze (B, A) - #define Blend_Stamp(A,B) ((uint8)((B + 2*A - 256 < 0) ? 0 : (B + 2*A - 256 > 255) ? 255 : (B + 2*A - 256) )) - #define Blend_Interpolate(A,B) ((uint8)((cos_table [A] + cos_table [B]> 255) ? 255 : (cos_table [A] + cos_table [B]) )) - - #define Blend_Xor(A,B) ((uint8) A ^ B ) - #define Blend_And(A,B) ((uint8) A & B ) - #define Blend_Or(A,B) ((uint8) A | B ) - #define Blend_A(A,B) ((uint8) (A)) - #define Blend_B(A,B) ((uint8) (B)) - #define Blend_It(Op) \ do \ if (Opacity < 1.0) \ --- 1814,1819 ---- *************** *** 1635,1641 **** pB [i] = Op (pA [i], pB [i]);\ while (false) - // we have to do this a row at a time, because there might be a filler at the end of each row // and thus, a discontinuity which throws out the r/g/b sequence #define Colour_Op(fR,fG,fB) \ --- 1824,1829 ---- *************** *** 1682,1698 **** while (false) - int BytesPerLine (int nWidth, int nBitsPerPixel) - { - return ( (nWidth * nBitsPerPixel + 31) & (~31) ) / 8; - } long CMiniWindow::BlendImage(LPCTSTR ImageId, long Left, long Top, long Right, long Bottom, short Mode, double Opacity, long SrcLeft, long SrcTop, long SrcRight, long SrcBottom) { ImageMapIterator it = m_Images.find (ImageId); if (it == m_Images.end ()) --- 1870,1894 ---- while (false) + // see also: CMUSHclientDoc::BlendPixel long CMiniWindow::BlendImage(LPCTSTR ImageId, long Left, long Top, long Right, long Bottom, short Mode, double Opacity, long SrcLeft, long SrcTop, long SrcRight, long SrcBottom) { + + // constrain to what we actually have + if (Left < 0) + Left = 0; + if (Top < 0) + Top = 0; + if (Right > m_iWidth) + Right = m_iWidth; + if (Bottom > m_iHeight) + Bottom = m_iHeight; + ImageMapIterator it = m_Images.find (ImageId); if (it == m_Images.end ()) *************** *** 1710,1715 **** --- 1906,1921 ---- long iWidth = FixRight (Right) - Left; long iHeight = FixBottom (Bottom) - Top; + // constrain to what we actually have + if (SrcLeft < 0) + SrcLeft = 0; + if (SrcTop < 0) + SrcTop = 0; + if (SrcRight > bi.bmWidth ) + SrcRight = bi.bmWidth ; + if (SrcBottom > bi.bmHeight) + SrcBottom = bi.bmHeight; + // adjust so that -1 means 1 from right if (SrcRight <= 0) SrcRight = bi.bmWidth + SrcRight; *************** *** 1717,1748 **** if (SrcBottom <= 0) SrcBottom = bi.bmHeight + SrcBottom; ! // width and heigh are the smaller of the two rectangles iWidth = min (iWidth, SrcRight - SrcLeft); iHeight = min (iHeight, SrcBottom - SrcTop); if (iWidth <= 0 || iHeight <= 0) // sanity check return eOK; // upper layer (from image id) CDC A_DC; A_DC.CreateCompatibleDC(&dc); - CBitmap A_bmp; - - BITMAPINFO bmiA; - ZeroMemory (&bmiA, sizeof bmiA); - - bmiA.bmiHeader.biSize = sizeof bmiA; - bmiA.bmiHeader.biWidth = iWidth; - bmiA.bmiHeader.biHeight = iHeight; - bmiA.bmiHeader.biPlanes = 1; - bmiA.bmiHeader.biBitCount = 24; - bmiA.bmiHeader.biCompression = BI_RGB; - bmiA.bmiHeader.biSizeImage = iHeight * BytesPerLine (iWidth, 24); unsigned char * pA = NULL; ! HBITMAP hbmA = CreateDIBSection(NULL, &bmiA, DIB_RGB_COLORS, (void**) &pA, NULL, 0); HBITMAP hOldAbmp = (HBITMAP) SelectObject(A_DC.m_hDC, hbmA); --- 1923,1953 ---- if (SrcBottom <= 0) SrcBottom = bi.bmHeight + SrcBottom; ! // width and height are the smaller of the two rectangles iWidth = min (iWidth, SrcRight - SrcLeft); iHeight = min (iHeight, SrcBottom - SrcTop); if (iWidth <= 0 || iHeight <= 0) // sanity check return eOK; + BITMAPINFO bmi; + ZeroMemory (&bmi, sizeof bmi); + + bmi.bmiHeader.biSize = sizeof bmi; + bmi.bmiHeader.biWidth = iWidth; + bmi.bmiHeader.biHeight = iHeight; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 24; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = iHeight * BytesPerLine (iWidth, 24); + // upper layer (from image id) CDC A_DC; A_DC.CreateCompatibleDC(&dc); unsigned char * pA = NULL; ! HBITMAP hbmA = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**) &pA, NULL, 0); HBITMAP hOldAbmp = (HBITMAP) SelectObject(A_DC.m_hDC, hbmA); *************** *** 1761,1780 **** B_DC.CreateCompatibleDC(&dc); CBitmap B_bmp; - BITMAPINFO bmiB; - ZeroMemory (&bmiB, sizeof bmiB); - - bmiB.bmiHeader.biSize = sizeof bmiB; - bmiB.bmiHeader.biWidth = iWidth; - bmiB.bmiHeader.biHeight = iHeight; - bmiB.bmiHeader.biPlanes = 1; - bmiB.bmiHeader.biBitCount = 24; - bmiB.bmiHeader.biCompression = BI_RGB; - bmiB.bmiHeader.biSizeImage = iHeight * BytesPerLine (iWidth, 24); - unsigned char * pB = NULL; ! HBITMAP hbmB = CreateDIBSection(dc.m_hDC, &bmiB, DIB_RGB_COLORS, (void**) &pB, NULL, 0); HBITMAP hOldBbmp = (HBITMAP) SelectObject(B_DC.m_hDC, hbmB); --- 1966,1974 ---- B_DC.CreateCompatibleDC(&dc); CBitmap B_bmp; unsigned char * pB = NULL; ! HBITMAP hbmB = CreateDIBSection(dc.m_hDC, &bmi, DIB_RGB_COLORS, (void**) &pB, NULL, 0); HBITMAP hOldBbmp = (HBITMAP) SelectObject(B_DC.m_hDC, hbmB); *************** *** 1785,1815 **** // manipulate image here A = blend, B = base ! long count = bmiB.bmiHeader.biSizeImage; long perline = BytesPerLine (iWidth, 24); long i, row; switch (Mode) { // normal modes ! case 1: Blend_It (Blend_Normal); break; ! case 2: Blend_It (Blend_Average); break; ! ! case 3: // Blend_Interpolate ! { ! // precompute cos table ! unsigned char cos_table [256]; ! double pi_div255 = 3.1415926535898 / 255.0; ! for (i = 0; i < 256; i++) ! { ! double a = 64.0 - cos ((double) i * pi_div255) * 64.0; ! cos_table [i] = (uint8) (a + 0.5); // round ! } ! Blend_It (Blend_Interpolate); ! } ! break; case 4: // dissolve - randomly choose pixels based on opacity for (i = 0; i < count; i++) --- 1979,2011 ---- // manipulate image here A = blend, B = base ! long count = bmi.bmiHeader.biSizeImage; long perline = BytesPerLine (iWidth, 24); long i, row; + // precompute cos table + static unsigned char cos_table [256]; + static bool bTableComputed = false; + + if (!bTableComputed) + { + double pi_div255 = 3.1415926535898 / 255.0; + for (i = 0; i < 256; i++) + { + double a = 64.0 - cos ((double) i * pi_div255) * 64.0; + cos_table [i] = (uint8) (a + 0.5); // round + } + bTableComputed = true; + } // table needs computing + switch (Mode) { // normal modes ! case 1: Blend_It (Blend_Normal); break; ! case 2: Blend_It (Blend_Average); break; ! case 3: Blend_It (Blend_Interpolate); break; case 4: // dissolve - randomly choose pixels based on opacity for (i = 0; i < count; i++) *************** *** 2160,2165 **** --- 2356,2544 ---- } // end of CMiniWindow::ImageFromWindow + static void HorizontalLinearGradient (const COLORREF StartColour, const double rdiff, const double gdiff, const double bdiff, + unsigned char * pBuffer, + const long iWidth, + const long iHeight) + { + double rval = GetRValue (StartColour), + gval = GetGValue (StartColour), + bval = GetBValue (StartColour); + + double rinc = rdiff / (double) (iWidth - 1), + ginc = gdiff / (double) (iWidth - 1), + binc = bdiff / (double) (iWidth - 1); + + long row, col; + uint8 r = 0, g = 0, b = 0; + + int increment = BytesPerLine (iWidth, 24); + + // main loop is columns + for (col = 0; col < iWidth; col++) + { + r = (uint8) rval; + g = (uint8) gval; + b = (uint8) bval; + unsigned char * p = pBuffer + col * 3; + for (row = 0; row < iHeight; row++) + { + p [0] = b; + p [1] = g; + p [2] = r; + p += increment; + } // end of each row + rval += rinc; + gval += ginc; + bval += binc; + } // end of each column + + + } // end of HorizontalLinearGradient + + + static void VerticalLinearGradient (const COLORREF EndColour, const double rdiff, const double gdiff, const double bdiff, + unsigned char * pBuffer, + const long iWidth, + const long iHeight) + { + double rval = GetRValue (EndColour), + gval = GetGValue (EndColour), + bval = GetBValue (EndColour); + + double rinc = - rdiff / (double) (iHeight - 1), + ginc = - gdiff / (double) (iHeight - 1), + binc = - bdiff / (double) (iHeight - 1); + + long row, col; + uint8 r = 0, g = 0, b = 0; + + int increment = BytesPerLine (iWidth, 24); + + // main loop is rows + for (row = 0; row < iHeight; row++) + { + r = (uint8) rval; + g = (uint8) gval; + b = (uint8) bval; + unsigned char * p = pBuffer + increment * row; + for (col = 0; col < iWidth; col++) + { + p [0] = b; + p [1] = g; + p [2] = r; + p += 3; + } // end of each column + rval += rinc; + gval += ginc; + bval += binc; + } // end of each row + + } // end of VerticalLinearGradient + + + static void MakeTexture (const COLORREF Multiplier, + unsigned char * pBuffer, + const long iWidth, + const long iHeight) + { + + long rval = GetRValue (Multiplier), + gval = GetGValue (Multiplier), + bval = GetBValue (Multiplier); + + long row, col; + long c; + + int increment = BytesPerLine (iWidth, 24); + + // main loop is columns + for (col = 0; col < iWidth; col++) + { + unsigned char * p = pBuffer + col * 3; + for (row = 0; row < iHeight; row++) + { + c = col ^ row; + p [0] = c * bval; + p [1] = c * gval; + p [2] = c * rval; + p += increment; + } // end of each row + } // end of each column + + + } // end of MakeTexture + + + // this is a load of old cobblers + + #if 0 + + static void HorizontalLogGradient (const COLORREF StartColour, const double rdiff, const double gdiff, const double bdiff, + unsigned char * pBuffer, + const long iWidth, + const long iHeight, + const bool rightToLeft) + { + double rval = GetRValue (StartColour), + gval = GetGValue (StartColour), + bval = GetBValue (StartColour); + + + double rfactor = pow (abs (rdiff), (double) 1.0 / (double) iWidth); + double gfactor = pow (abs (gdiff), (double) 1.0 / (double) iWidth); + double bfactor = pow (abs (bdiff), (double) 1.0 / (double) iWidth); + + + long row, col; + uint8 r = 0, g = 0, b = 0; + + double rinc = rfactor, + ginc = gfactor, + binc = bfactor; + + int increment = BytesPerLine (iWidth, 24); + + // main loop is columns + for (col = 0; col < iWidth; col++) + { + + + r = (uint8) rval; + g = (uint8) gval; + b = (uint8) bval; + unsigned char * p = pBuffer + col * 3; + for (row = 0; row < iHeight; row++) + { + p [0] = b; + p [1] = g; + p [2] = r; + p += increment; + } // end of each row + + rinc *= rfactor; + ginc *= gfactor; + binc *= bfactor; + + if (rightToLeft) + { + rval = GetRValue (StartColour) - rinc; + gval = GetGValue (StartColour) - ginc; + bval = GetBValue (StartColour) - binc; + } + else + { + rval = GetRValue (StartColour) + rinc; + gval = GetGValue (StartColour) + ginc; + bval = GetBValue (StartColour) + binc; + } + } // end of each column + + + } // end of HorizontalLogGradient + + #endif // 0 + long CMiniWindow::Gradient(long Left, long Top, long Right, long Bottom, long StartColour, long EndColour, short Mode) *************** *** 2193,2270 **** HBITMAP hOldAbmp = (HBITMAP) SelectObject(gDC.m_hDC, hbmG); - long row, col; double rdiff = GetRValue (EndColour) - GetRValue (StartColour), gdiff = GetGValue (EndColour) - GetGValue (StartColour), bdiff = GetBValue (EndColour) - GetBValue (StartColour); - double rinc = 0, ginc = 0, binc = 0; - uint8 r = 0, g = 0, b = 0; switch (Mode) { case 1 : // horizontal (left to right) ! { ! double rval = GetRValue (StartColour), ! gval = GetGValue (StartColour), ! bval = GetBValue (StartColour); ! rinc = rdiff / (double) (iWidth - 1); ! ginc = gdiff / (double) (iWidth - 1); ! binc = bdiff / (double) (iWidth - 1); ! ! // main loop is columns ! for (col = 0; col < iWidth; col++) ! { ! r = (uint8) rval; ! g = (uint8) gval; ! b = (uint8) bval; ! unsigned char * p = pA + col * 3; ! for (row = 0; row < iHeight; row++) ! { ! p [0] = b; ! p [1] = g; ! p [2] = r; ! p += BytesPerLine (iWidth, 24); ! } // end of each row ! rval += rinc; ! gval += ginc; ! bval += binc; ! } // end of each column ! } break; // end of horizontal case 2 : // vertical (top to bottom) ! { ! double rval = GetRValue (EndColour), ! gval = GetGValue (EndColour), ! bval = GetBValue (EndColour); ! rinc = - rdiff / (double) (iHeight - 1); ! ginc = - gdiff / (double) (iHeight - 1); ! binc = - bdiff / (double) (iHeight - 1); ! ! // main loop is rows ! for (row = 0; row < iHeight; row++) ! { ! r = (uint8) rval; ! g = (uint8) gval; ! b = (uint8) bval; ! unsigned char * p = pA + BytesPerLine (iWidth, 24) * row; ! for (col = 0; col < iWidth; col++) ! { ! p [0] = b; ! p [1] = g; ! p [2] = r; ! p += 3; ! } // end of each column ! rval += rinc; ! gval += ginc; ! bval += binc; ! } // end of each row ! } break; // end of vertical default: return eUnknownOption; --- 2572,2610 ---- HBITMAP hOldAbmp = (HBITMAP) SelectObject(gDC.m_hDC, hbmG); double rdiff = GetRValue (EndColour) - GetRValue (StartColour), gdiff = GetGValue (EndColour) - GetGValue (StartColour), bdiff = GetBValue (EndColour) - GetBValue (StartColour); switch (Mode) { case 1 : // horizontal (left to right) ! HorizontalLinearGradient (StartColour, rdiff, gdiff, bdiff, pA, iWidth, iHeight); break; // end of horizontal case 2 : // vertical (top to bottom) ! VerticalLinearGradient (EndColour, rdiff, gdiff, bdiff, pA, iWidth, iHeight); break; // end of vertical + case 3 : // texture + MakeTexture (StartColour, pA, iWidth, iHeight); + break; // end of texture + + // forget it! + + #if 0 + case 3 : // horizontal (left to right) + HorizontalLogGradient (StartColour, rdiff, gdiff, bdiff, pA, iWidth, iHeight, false); + break; // end of horizontal + + case 4 : // horizontal (right to left) + HorizontalLogGradient (EndColour, rdiff, gdiff, bdiff, pA, iWidth, iHeight, true); + break; // end of horizontal + + #endif // 0 default: return eUnknownOption; *************** *** 2385,2392 **** } // end of Blur - #define CLAMP(x) (((x) < 0) ? 0 : (c > 255) ? 255 : (x)) - static void Noise (unsigned char * inbuf, long iWidth, long iHeight, long iPerLine, double Options) { --- 2725,2730 ---- *************** *** 2448,2453 **** --- 2786,2806 ---- } // end of Brightness + static void BrightnessMultiply (unsigned char * inbuf, long iWidth, long iHeight, long iPerLine, double Options) + { + + unsigned char * pi = inbuf; + long count = iPerLine * iHeight; + long i, c; + for (i = 0; i < count; i++) + { + c = *pi; + c *= Options; + *pi++ = CLAMP (c); + } + + } // end of BrightnessMultiply + static void Contrast (unsigned char * inbuf, long iWidth, long iHeight, long iPerLine, double Options) { *************** *** 2520,2525 **** --- 2873,2899 ---- } // end of ColourBrightness + static void ColourBrightnessMultiply (unsigned char * inbuf, long iWidth, long iHeight, + long iPerLine, double Options, long iColour) + { + + long i, row, c; + + for (row = 0; row < iHeight; row++) + { + unsigned char * pi = inbuf + (row * iPerLine) + iColour; + for (i = 0; i < iWidth; i ++) + { + c = *pi; + c *= Options; + *pi = CLAMP (c); + pi += 3; + } + } // end for each row + + } // end of ColourBrightnessMultiply + + static void ColourContrast (unsigned char * inbuf, long iWidth, long iHeight, long iPerLine, double Options, long iColour) { *************** *** 2593,2599 **** long count = iPerLine * iHeight / 3; long i, row; double c; - double threshold = Options / 100.0; for (row = 0; row < iHeight; row++) --- 2967,2972 ---- *************** *** 2622,2636 **** } // end of MakeGreyscale long CMiniWindow::Filter(long Left, long Top, long Right, long Bottom, short Operation, double Options) { // calculate size of desired rectangle long iWidth = FixRight (Right) - Left; long iHeight = FixBottom (Bottom) - Top; ! if (iWidth <= 3 || iHeight <= 3) // sanity check return eOK; // upper layer (from image id) --- 2995,3068 ---- } // end of MakeGreyscale + static void Average (unsigned char * pBuffer, + const long iWidth, + const long iHeight) + { + + long row, col; + __int64 r = 0, g = 0, b = 0, count = 0; + + int increment = BytesPerLine (iWidth, 24); + + // find average + + // main loop is columns + for (col = 0; col < iWidth; col++) + { + unsigned char * p = pBuffer + col * 3; + for (row = 0; row < iHeight; row++) + { + b += p [0]; + g += p [1]; + r += p [2]; + count++; + p += increment; + } // end of each row + } // end of each column + + r /= count; + g /= count; + b /= count; + + // apply average + + // main loop is columns + for (col = 0; col < iWidth; col++) + { + unsigned char * p = pBuffer + col * 3; + for (row = 0; row < iHeight; row++) + { + p [0] = CLAMP (b); + p [1] = CLAMP (g); + p [2] = CLAMP (r); + p += increment; + } // end of each row + } // end of each column + + } // end of Average + + + // see also: CMUSHclientDoc::FilterPixel long CMiniWindow::Filter(long Left, long Top, long Right, long Bottom, short Operation, double Options) { + // constrain to what we actually have + if (Left < 0) + Left = 0; + if (Top < 0) + Top = 0; + if (Right > m_iWidth) + Right = m_iWidth; + if (Bottom > m_iHeight) + Bottom = m_iHeight; + // calculate size of desired rectangle long iWidth = FixRight (Right) - Left; long iHeight = FixBottom (Bottom) - Top; ! if (iWidth < 1 || iHeight < 1) // sanity check return eOK; // upper layer (from image id) *************** *** 2688,2694 **** GeneralFilter (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, iMatrix, 1); } break; ! case 7: Brightness (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options); break; case 8: Contrast (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options); break; case 9: Gamma (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options); break; case 10: ColourBrightness (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, 2); break; // red --- 3120,3126 ---- GeneralFilter (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, iMatrix, 1); } break; ! case 7: Brightness (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options); break; // additive brightness case 8: Contrast (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options); break; case 9: Gamma (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options); break; case 10: ColourBrightness (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, 2); break; // red *************** *** 2702,2707 **** --- 3134,3156 ---- case 18: ColourGamma (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, 0); break; // blue case 19: MakeGreyscale (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, true); break; // linear case 20: MakeGreyscale (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, false); break; // perceptual + case 21: BrightnessMultiply(pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options); break; // multiplicative brightness + case 22: ColourBrightnessMultiply(pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, 2); break; // red + case 23: ColourBrightnessMultiply(pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, 1); break; // green + case 24: ColourBrightnessMultiply(pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, 0); break; // blue + case 25: // lesser blur + { + double iMatrix [5] = { 0, 1, 1, 1, 0 }; + GeneralFilter (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, iMatrix, 3); + } + break; + case 26: // minor blur + { + double iMatrix [5] = { 0, 0.5, 1, 0.5, 0 }; + GeneralFilter (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, iMatrix, 2); + } + break; + case 27: Average (pA, iWidth, iHeight); break; *************** *** 2721,2724 **** --- 3170,3447 ---- return eOK; } // end of CMiniWindow::Filter + + + + long CMiniWindow::SetPixel(long x, long y, long Colour) + { + dc.SetPixelV(x, y, Colour); + return eOK; + } // end of CMiniWindow::SetPixel + + + long CMiniWindow::GetPixel(long x, long y) + { + return dc.GetPixel(x, y); + } // end of CMiniWindow::GetPixel + + + long CMiniWindow::MergeImageAlpha(LPCTSTR ImageId, LPCTSTR MaskId, + long Left, long Top, long Right, long Bottom, + short Mode, double Opacity, + long SrcLeft, long SrcTop, long SrcRight, long SrcBottom) + { + + // constrain to what we actually have + if (Left < 0) + Left = 0; + if (Top < 0) + Top = 0; + if (Right > m_iWidth) + Right = m_iWidth; + if (Bottom > m_iHeight) + Bottom = m_iHeight; + + if (Opacity < 0.0 || Opacity > 1.0) + return eBadParameter; + + // image to be merged + ImageMapIterator it = m_Images.find (ImageId); + + if (it == m_Images.end ()) + return eImageNotInstalled; + + CBitmap * bitmap = it->second; + + // mask image + it = m_Images.find (MaskId); + + if (it == m_Images.end ()) + return eImageNotInstalled; + + CBitmap * mask_bitmap = it->second; + + BITMAP bi; + bitmap->GetBitmap(&bi); + + // calculate size of desired rectangle + long iWidth = FixRight (Right) - Left; + long iHeight = FixBottom (Bottom) - Top; + + // constrain to what we actually have + if (SrcLeft < 0) + SrcLeft = 0; + if (SrcTop < 0) + SrcTop = 0; + if (SrcRight > bi.bmWidth ) + SrcRight = bi.bmWidth ; + if (SrcBottom > bi.bmHeight) + SrcBottom = bi.bmHeight; + + // adjust so that -1 means 1 from right + if (SrcRight <= 0) + SrcRight = bi.bmWidth + SrcRight; + + if (SrcBottom <= 0) + SrcBottom = bi.bmHeight + SrcBottom; + + // width and height are the smaller of the two rectangles + iWidth = min (iWidth, SrcRight - SrcLeft); + iHeight = min (iHeight, SrcBottom - SrcTop); + + if (iWidth <= 0 || iHeight <= 0) // sanity check + return eOK; + + mask_bitmap->GetBitmap(&bi); + + // adjust down in case we don't use whole image + SrcRight = SrcLeft + iWidth; + SrcBottom = SrcTop + iHeight; + + // mask must at least be as big as the image we are merging + if (bi.bmWidth < SrcRight) + return eBadParameter; + if (bi.bmHeight < SrcBottom) + return eBadParameter; + + + // merge layer (from image id) + CDC A_DC; + A_DC.CreateCompatibleDC(&dc); + + BITMAPINFO bmi; + ZeroMemory (&bmi, sizeof bmi); + + bmi.bmiHeader.biSize = sizeof bmi; + bmi.bmiHeader.biWidth = iWidth; + bmi.bmiHeader.biHeight = iHeight; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 24; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = iHeight * BytesPerLine (iWidth, 24); + + unsigned char * pA = NULL; + + HBITMAP hbmA = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**) &pA, NULL, 0); + + HBITMAP hOldAbmp = (HBITMAP) SelectObject(A_DC.m_hDC, hbmA); + + CDC bmDC; // for loading bitmaps into + bmDC.CreateCompatibleDC(&dc); + + //copy part from image to upper layer + CBitmap *pOldbmp = bmDC.SelectObject(bitmap); + A_DC.BitBlt (0, 0, iWidth, iHeight, &bmDC, SrcLeft, SrcTop, SRCCOPY); + bmDC.SelectObject(pOldbmp); + + + // base image (from miniwindow) + + CDC B_DC; + B_DC.CreateCompatibleDC(&dc); + CBitmap B_bmp; + + unsigned char * pB = NULL; + + HBITMAP hbmB = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**) &pB, NULL, 0); + + HBITMAP hOldBbmp = (HBITMAP) SelectObject(B_DC.m_hDC, hbmB); + + // copy base image from miniwindow to bitmap + B_DC.BitBlt (0, 0, iWidth, iHeight, &dc, Left, Top, SRCCOPY); + + + // mask image + + CDC M_DC; + M_DC.CreateCompatibleDC(&dc); + CBitmap M_bmp; + + unsigned char * pM = NULL; + + HBITMAP hbmM = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**) &pM, NULL, 0); + + HBITMAP hOldMbmp = (HBITMAP) SelectObject(M_DC.m_hDC, hbmM); + + // copy mask image from image to bitmap + pOldbmp = bmDC.SelectObject(mask_bitmap); + M_DC.BitBlt (0, 0, iWidth, iHeight, &bmDC, SrcLeft, SrcTop, SRCCOPY); + bmDC.SelectObject(pOldbmp); + + long count = bmi.bmiHeader.biSizeImage; + long perline = BytesPerLine (iWidth, 24); + + long i; + + // do the merge + + #define Blend_Mask(A,B,M) ((uint8) ((A * M + B * (255 - M)) / 255) ) + + switch (Mode) + { + case 0: // normal + if (Opacity < 1.0) + { + for (i = 0; i < count; i++) + { + pB [i] = Simple_Opacity (pB [i], Blend_Mask (pA [i], pB [i], pM [i]), Opacity); + } + } + else + { + for (i = 0; i < count; i ++) + pB [i] = Blend_Mask (pA [i], pB [i], pM [i]); + } + break; // end of mode 0 + + case 1: // transparent on pixel at 0,0 + { + COLORREF opaque = ::GetPixel (A_DC, 0, 0); + + long row; + for (row = 0; row < iHeight; row++) + { + long base = row * perline; + unsigned char rA, gA, bA, rB, gB, bB; + if (Opacity < 1.0) + for (i = 0; i < perline - 2; ) + { + bA = pA [base + i]; + gA = pA [base + i + 1]; + rA = pA [base + i + 2]; + bB = pB [base + i]; + gB = pB [base + i + 1]; + rB = pB [base + i + 2]; + + // if this pixel is the opaque one, take the base pixel instead + if (RGB (rA, gA, bA) == opaque) + { + rA = rB; + gA = gB; + bA = bB; + } + + pB [base + i] = Simple_Opacity (bB, Blend_Mask (bA, bB, pM [base + i]), Opacity); + i++; + + pB [base + i] = Simple_Opacity (gB, Blend_Mask (gA, gB, pM [base + i]), Opacity); + i++; + + pB [base + i] = Simple_Opacity (rB, Blend_Mask (rA, rB, pM [base + i]), Opacity); + i++; + } + else + for (i = 0; i < perline - 2;) + { + bA = pA [base + i]; + gA = pA [base + i + 1]; + rA = pA [base + i + 2]; + bB = pB [base + i]; + gB = pB [base + i + 1]; + rB = pB [base + i + 2]; + + // if this pixel is the opaque one, take the base pixel instead + if (RGB (rA, gA, bA) == opaque) + { + rA = rB; + gA = gB; + bA = bB; + } + + pB [base + i] = Blend_Mask (bA, bB, pM [base + i]); + i++; + + pB [base + i] = Blend_Mask (gA, gB, pM [base + i]); + i++; + + pB [base + i] = Blend_Mask (rA, rB, pM [base + i]); + i++; + } // end Opacity == 1 + } // end for loop + + + } + break; // end of mode 1 + + default: return eUnknownOption; + + } // end of switch on Mode + + + // copy result back + + dc.BitBlt (Left, Top, iWidth, iHeight, &B_DC, 0, 0, SRCCOPY); + + + SelectObject(A_DC.m_hDC, hOldAbmp); + SelectObject(B_DC.m_hDC, hOldBbmp); + SelectObject(M_DC.m_hDC, hOldMbmp); + + DeleteObject (hbmA); + DeleteObject (hbmB); + DeleteObject (hbmM); + + return eOK; + + } // end of CMiniWindow::MergeImageAlpha Index: mushclient.cnt =================================================================== RCS file: /cvs/mushclient/mushclient.cnt,v retrieving revision 1.55 retrieving revision 1.57 diff -c -r1.55 -r1.57 *** mushclient.cnt 2 Aug 2008 06:35:23 -0000 1.55 --- mushclient.cnt 26 Aug 2008 05:23:14 -0000 1.57 *************** *** 195,200 **** --- 195,201 ---- 3 ArraySize=FNC_ArraySize 3 Base64Decode=FNC_Base64Decode 3 Base64Encode=FNC_Base64Encode + 3 BlendPixel=FNC_BlendPixel 3 BoldColour=FNC_BoldColour 3 BroadcastPlugin=FNC_BroadcastPlugin 3 CallPlugin=FNC_CallPlugin *************** *** 269,274 **** --- 270,276 ---- 3 EvaluateSpeedwalk=FNC_EvaluateSpeedwalk 3 Execute=FNC_Execute 3 ExportXML=FNC_ExportXML + 3 FilterPixel=FNC_FilterPixel 3 FixupEscapeSequences=FNC_FixupEscapeSequences 3 FixupHTML=FNC_FixupHTML 3 FlushLog=FNC_FlushLog *************** *** 504,509 **** --- 506,512 ---- 3 WindowFont=FNC_WindowFont 3 WindowFontInfo=FNC_WindowFontInfo 3 WindowFontList=FNC_WindowFontList + 3 WindowGetPixel=FNC_WindowGetPixel 3 WindowImageFromWindow=FNC_WindowImageFromWindow 3 WindowImageInfo=FNC_WindowImageInfo 3 WindowImageList=FNC_WindowImageList *************** *** 514,525 **** --- 517,531 ---- 3 WindowLine=FNC_WindowLine 3 WindowList=FNC_WindowList 3 WindowLoadImage=FNC_WindowLoadImage + 3 WindowMergeImageAlpha=FNC_WindowMergeImageAlpha 3 WindowPolygon=FNC_WindowPolygon 3 WindowPosition=FNC_WindowPosition 3 WindowRectOp=FNC_WindowRectOp + 3 WindowSetPixel=FNC_WindowSetPixel 3 WindowShow=FNC_WindowShow 3 WindowText=FNC_WindowText 3 WindowTextWidth=FNC_WindowTextWidth + 3 WindowWrite=FNC_WindowWrite 3 WorldAddress=FNC_WorldAddress 3 WorldName=FNC_WorldName 3 WorldPort=FNC_WorldPort Index: mushclient.hlp =================================================================== RCS file: /cvs/mushclient/mushclient.hlp,v retrieving revision 1.101 retrieving revision 1.102 diff -c -r1.101 -r1.102 Binary files /tmp/cvs0FE2xV and /tmp/cvsFC2RTW differ Index: mushclient.odl =================================================================== RCS file: /cvs/mushclient/mushclient.odl,v retrieving revision 1.137 retrieving revision 1.139 diff -c -r1.137 -r1.139 *** mushclient.odl 5 Aug 2008 06:25:12 -0000 1.137 --- mushclient.odl 26 Aug 2008 05:23:14 -0000 1.139 *************** *** 70,83 **** [id(44)] long SetCommand(BSTR Message); [id(45)] BSTR GetNotes(); [id(46)] void SetNotes(BSTR Message); ! [id(364), propget] long NormalColour(short WhichColour); ! [id(364), propput] void NormalColour(short WhichColour, long nNewValue); ! [id(365), propget] long BoldColour(short WhichColour); ! [id(365), propput] void BoldColour(short WhichColour, long nNewValue); ! [id(366), propget] long CustomColourText(short WhichColour); ! [id(366), propput] void CustomColourText(short WhichColour, long nNewValue); ! [id(367), propget] long CustomColourBackground(short WhichColour); ! [id(367), propput] void CustomColourBackground(short WhichColour, long nNewValue); [id(47)] void Redraw(); [id(48)] long ResetTimer(BSTR TimerName); [id(49)] void SetOutputFont(BSTR FontName, short PointSize); --- 70,83 ---- [id(44)] long SetCommand(BSTR Message); [id(45)] BSTR GetNotes(); [id(46)] void SetNotes(BSTR Message); ! [id(370), propget] long NormalColour(short WhichColour); ! [id(370), propput] void NormalColour(short WhichColour, long nNewValue); ! [id(371), propget] long BoldColour(short WhichColour); ! [id(371), propput] void BoldColour(short WhichColour, long nNewValue); ! [id(372), propget] long CustomColourText(short WhichColour); ! [id(372), propput] void CustomColourText(short WhichColour, long nNewValue); ! [id(373), propget] long CustomColourBackground(short WhichColour); ! [id(373), propput] void CustomColourBackground(short WhichColour, long nNewValue); [id(47)] void Redraw(); [id(48)] long ResetTimer(BSTR TimerName); [id(49)] void SetOutputFont(BSTR FontName, short PointSize); *************** *** 395,400 **** --- 395,406 ---- [id(361)] long TextRectangle(long Left, long Top, long Right, long Bottom, long BorderOffset, long BorderColour, long BorderWidth, long OutsideFillColour, long OutsideFillStyle); [id(362)] long WindowGradient(BSTR Name, long Left, long Top, long Right, long Bottom, long StartColour, long EndColour, short Mode); [id(363)] long WindowFilter(BSTR Name, long Left, long Top, long Right, long Bottom, short Operation, double Options); + [id(364)] long WindowSetPixel(BSTR Name, long x, long y, long Colour); + [id(365)] long WindowGetPixel(BSTR Name, long x, long y); + [id(366)] long WindowWrite(BSTR Name, BSTR FileName); + [id(367)] long FilterPixel(long Pixel, short Operation, double Options); + [id(368)] long BlendPixel(long Blend, long Base, short Mode, double Opacity); + [id(369)] long WindowMergeImageAlpha(BSTR Name, BSTR ImageId, BSTR MaskId, long Left, long Top, long Right, long Bottom, short Mode, double Opacity, long SrcLeft, long SrcTop, long SrcRight, long SrcBottom); //}}AFX_ODL_METHOD }; Index: mushview.cpp =================================================================== RCS file: /cvs/mushclient/mushview.cpp,v retrieving revision 1.113 retrieving revision 1.115 diff -c -r1.113 -r1.115 *** mushview.cpp 5 Aug 2008 06:25:12 -0000 1.113 --- mushview.cpp 26 Aug 2008 05:23:14 -0000 1.115 *************** *** 986,992 **** startline = (pt.y - pDoc->m_iPixelOffset) / pDoc->m_FontHeight; ! endline = ((pt.y + GetOutputWindowHeight ()) / pDoc->m_FontHeight) + 2; if (startline < 0) startline = 0; --- 986,992 ---- startline = (pt.y - pDoc->m_iPixelOffset) / pDoc->m_FontHeight; ! endline = ((pt.y + GetOutputWindowHeight ()) / pDoc->m_FontHeight); if (startline < 0) startline = 0; *************** *** 1885,1891 **** dc.DPtoLP(&point); // if click in mini-window, don't continue ! if (Mouse_Down_MiniWindow (pDoc, point, 0x10)) // LH mouse, singe click return; // check for the rectangle, now we are past the miniwindow stuff --- 1885,1891 ---- dc.DPtoLP(&point); // if click in mini-window, don't continue ! if (Mouse_Down_MiniWindow (pDoc, point, 0x10)) // LH mouse, single click return; // check for the rectangle, now we are past the miniwindow stuff *************** *** 1922,1928 **** int iCol; // don't do it *past* end of last word ! long pixel = calculate_width (line, pLine->len, pDoc, dc) + pDoc->m_iPixelOffset; if (point.x < pixel && pDoc->FindStyle (pLine, col, iCol, pStyle, foundpos)) --- 1922,1928 ---- int iCol; // don't do it *past* end of last word ! long pixel = calculate_width (line, pLine->len, pDoc, dc) + pDoc->m_iPixelOffset + pDoc->m_TextRectangle.left; if (point.x < pixel && pDoc->FindStyle (pLine, col, iCol, pStyle, foundpos)) *************** *** 2847,2852 **** --- 2847,2869 ---- Frame.FixUpTitleBar (); // in case we need to add the mud name to the title bar + // tell each plugin we have resized. Hello, Worstje! + + for (POSITION pluginpos = pDoc->m_PluginList.GetHeadPosition(); pluginpos; ) + { + CPlugin * pPlugin = pDoc->m_PluginList.GetNext (pluginpos); + + + if (!(pPlugin->m_bEnabled)) // ignore disabled plugins + continue; + + // see what the plugin makes of this, + pPlugin->ExecutePluginScript (ON_PLUGIN_WORLD_OUTPUT_RESIZED, + pPlugin->m_dispid_plugin_on_world_output_resized); + + } // end of doing each plugin + + // this is for the guy that wants to fit the max text he can in his window, // after resizing it *************** *** 5452,5466 **** void CMUSHView::SelectLine (const int iLine) { - CRgn oldrgn; - CRgn newrgn; - - // Invalidate old selection rectangle - - // Get old selection region - - get_selection (oldrgn); - // select the found text, so it is highlighted m_selstart_line = iLine; --- 5469,5474 ---- *************** *** 5468,5492 **** m_selstart_col = 0; m_selend_col = 0; - // Invalidate new selection rectangle - - // Get new selection region - - get_selection (newrgn); - - // Combine previously selected with new selection, excluding union - oldrgn.CombineRgn (&oldrgn, &newrgn, RGN_XOR); - - // Invalidate new stuff - InvalidateRgn (&oldrgn); #if REDRAW_DEBUG ShowInvalidatedRgn (this, oldrgn); #endif ! // Finished with regions ! newrgn.DeleteObject (); ! oldrgn.DeleteObject (); // freeze output, so they can study the found text at leisure --- 5476,5487 ---- m_selstart_col = 0; m_selend_col = 0; #if REDRAW_DEBUG ShowInvalidatedRgn (this, oldrgn); #endif ! Invalidate (); // freeze output, so they can study the found text at leisure Index: plugins.cpp =================================================================== RCS file: /cvs/mushclient/plugins.cpp,v retrieving revision 1.43 retrieving revision 1.44 diff -c -r1.43 -r1.44 *** plugins.cpp 6 Jul 2008 03:41:06 -0000 1.43 --- plugins.cpp 26 Aug 2008 05:23:14 -0000 1.44 *************** *** 51,56 **** --- 51,57 ---- m_dispid_plugin_packet_received = DISPID_UNKNOWN; m_dispid_plugin_telnet_option = DISPID_UNKNOWN; m_dispid_plugin_partial_line = DISPID_UNKNOWN; + m_dispid_plugin_on_world_output_resized = DISPID_UNKNOWN; m_dispid_plugin_OnMXP_Start = DISPID_UNKNOWN; m_dispid_plugin_OnMXP_Stop = DISPID_UNKNOWN; Index: sendvw.cpp =================================================================== RCS file: /cvs/mushclient/sendvw.cpp,v retrieving revision 1.87 retrieving revision 1.88 diff -c -r1.87 -r1.88 *** sendvw.cpp 29 Jun 2008 00:04:24 -0000 1.87 --- sendvw.cpp 26 Aug 2008 05:23:14 -0000 1.88 *************** *** 1381,1396 **** if (found) { - // Invalidate old selection rectangle - - - CRgn oldrgn; - CRgn newrgn; - - // Get old selection region - - m_topview->get_selection (oldrgn); - // because find now finds batches of lines, we must work out which line it is // really on, so we highlight the correct columns --- 1381,1386 ---- *************** *** 1454,1481 **** } } - // Invalidate new selection rectangle - - // Get new selection region - - m_topview->get_selection (newrgn); - - // Combine previously selected with new selection, excluding union - oldrgn.CombineRgn (&oldrgn, &newrgn, RGN_XOR); - - // Invalidate new stuff - m_topview->InvalidateRgn (&oldrgn); - - // Finished with regions - newrgn.DeleteObject (); - oldrgn.DeleteObject (); - // make sure selection visible m_topview->EnsureSelectionVisible (); } // end of being found } // end of CSendView::DoFind --- 1444,1457 ---- } } // make sure selection visible m_topview->EnsureSelectionVisible (); } // end of being found + // Invalidate new selection rectangle + m_topview->Invalidate (); } // end of CSendView::DoFind *************** *** 2829,2837 **** if (iLines < pDoc->m_iAutoResizeMinimumLines) iLines = pDoc->m_iAutoResizeMinimumLines; ! // if very large, let them manage it if (iLines > pDoc->m_iAutoResizeMaximumLines) ! return; // resize - seem to need an extra 4 pixels or things go a bit strange pDoc->SetCommandWindowHeight (pDoc->m_InputFontHeight * iLines + 4); --- 2805,2822 ---- if (iLines < pDoc->m_iAutoResizeMinimumLines) iLines = pDoc->m_iAutoResizeMinimumLines; ! CRect rect; ! GetClientRect (&rect); ! if (iLines > pDoc->m_iAutoResizeMaximumLines) ! { ! // if very large, let them manage it (that is, if they have already resized it to be larger than the maximum) ! if ((rect.bottom - rect.top) > (pDoc->m_InputFontHeight * pDoc->m_iAutoResizeMaximumLines + 4)) ! return; ! ! // otherwise, take the maximum ! iLines = pDoc->m_iAutoResizeMaximumLines; ! } // resize - seem to need an extra 4 pixels or things go a bit strange pDoc->SetCommandWindowHeight (pDoc->m_InputFontHeight * iLines + 4); Index: stdafx.h =================================================================== RCS file: /cvs/mushclient/stdafx.h,v retrieving revision 1.110 retrieving revision 1.112 diff -c -r1.110 -r1.112 *** stdafx.h 30 Jul 2008 22:40:58 -0000 1.110 --- stdafx.h 26 Aug 2008 05:23:14 -0000 1.112 *************** *** 505,510 **** --- 505,511 ---- #define ON_PLUGIN_PACKET_RECEIVED "OnPluginPacketReceived" #define ON_PLUGIN_PARTIAL_LINE "OnPluginPartialLine" #define ON_PLUGIN_TELNET_OPTION "OnPluginTelnetOption" + #define ON_PLUGIN_WORLD_OUTPUT_RESIZED "OnPluginWorldOutputResized" // MXP stuff #define ON_PLUGIN_MXP_START "OnPluginMXPstart" *************** *** 836,838 **** --- 837,896 ---- #define IsCTRLpressed() ( (GetKeyState(VK_CONTROL) & (1 << (sizeof(SHORT)*8-1))) != 0 ) #define IsSHIFTpressed() ( (GetKeyState(VK_SHIFT) & (1 << (sizeof(SHORT)*8-1))) != 0 ) + // colour stuff + + #define CLAMP(x) (((x) < 0) ? 0 : (x > 255) ? 255 : (x)) + + + // see: http://www.nathanm.com/photoshop-blending-math/ + // and: http://www.pegtop.net/delphi/articles/blendmodes/ + + #define uint8 unsigned char + #define sqr(x) ((x)*(x)) // square of x + + // A = blend, B = base + + #define Blend_Normal(A,B) ((uint8)(A)) + #define Blend_Lighten(A,B) ((uint8)((B > A) ? B:A)) + #define Blend_Darken(A,B) ((uint8)((B > A) ? A:B)) + #define Blend_Multiply(A,B) ((uint8)((A * B) / 255)) + #define Blend_Average(A,B) ((uint8)((A + B) / 2)) + #define Blend_Add(A,B) ((uint8)((A + B > 255) ? 255:(A + B))) + #define Blend_Subtract(A,B) ((uint8)((A + B < 255) ? 0:(A + B - 255))) + #define Blend_Difference(A,B) ((uint8)(abs(A - B))) + #define Blend_Negation(A,B) ((uint8)(255 - abs(255 - A - B))) + #define Blend_Screen(A,B) ((uint8)(255 - (((255 - A) * (255 - B)) >> 8))) + #define Blend_Exclusion(A,B) ((uint8)(A + B - 2 * A * B / 255)) + #define Blend_Overlay(A,B) ((uint8)((B < 128) ? (2 * A * B / 255):(255 - 2 * (255 - A) * (255 - B) / 255))) + #define Blend_SoftLight(A,B) ((uint8) ((A * B) >> 8) + ((B * (255 - (((255 - B) * (255-A)) >> 8) - ((A * B) >> 8) )) >> 8) ) // c = ((A * B) >> 8) + #define Blend_HardLight(A,B) (Blend_Overlay(B,A)) + #define Blend_ColorDodge(A,B) ((uint8)((A == 255) ? A:((((unsigned long) B) << 8 ) / (255 - A) > 255) ? 255:((((unsigned long) B) << 8 ) / (255 - A)))) + #define Blend_ColorBurn(A,B) ((uint8)((A == 0) ? 0:((255 - (( ((unsigned long)(255 - B)) << 8 ) / A)) < 0) ? 0:(255 - (( ((unsigned long)(255 - B)) << 8 ) / A)))) + #define Blend_LinearDodge(A,B) (Blend_Add(A,B)) + #define Blend_LinearBurn(A,B) (Blend_Subtract(A,B)) + #define Blend_LinearLight(A,B) ((uint8)(A < 128) ? Blend_LinearBurn((2 * A),B):Blend_LinearDodge((2 * (A - 128)),B)) + #define Blend_VividLight(A,B) ((uint8)(A < 128) ? Blend_ColorBurn((2 * A),B):Blend_ColorDodge((2 * (A - 128)),B)) + #define Blend_PinLight(A,B) ((uint8)(A < 128) ? Blend_Darken((2 * A),B):Blend_Lighten((2 *(A - 128)),B)) + #define Blend_HardMix(A,B) ((uint8)(A < 255 - B) ? 0:255) + #define Blend_Reflect(A,B) ((uint8)((B == 255) ? B:((A * A / (255 - B) > 255) ? 255:(A * A / (255 - B))))) + #define Blend_Glow(A,B) (Blend_Reflect(B,A)) + #define Blend_Phoenix(A,B) ((uint8)(min(A,B) - max(A,B) + 255)) + #define Blend_Opacity(A,B,F,O) ((uint8)(O * F(A,B) + (1 - O) * B)) + + #define Simple_Opacity(B,X,O) ((uint8)(O * X + (1 - O) * B)) + + #define Blend_InverseColorDodge(A,B) Blend_ColorDodge (B, A) + #define Blend_InverseColorBurn(A,B) Blend_ColorBurn (B, A) + #define Blend_Freeze(A,B) ((uint8)((A == 0) ? A:((255 - sqr(255 - B)/ A < 0) ? 0:(255 - sqr(255 - B) / A)))) + #define Blend_Heat(A,B) Blend_Freeze (B, A) + #define Blend_Stamp(A,B) ((uint8)((B + 2*A - 256 < 0) ? 0 : (B + 2*A - 256 > 255) ? 255 : (B + 2*A - 256) )) + #define Blend_Interpolate(A,B) ((uint8)((cos_table [A] + cos_table [B]> 255) ? 255 : (cos_table [A] + cos_table [B]) )) + + #define Blend_Xor(A,B) ((uint8) A ^ B ) + #define Blend_And(A,B) ((uint8) A & B ) + #define Blend_Or(A,B) ((uint8) A | B ) + #define Blend_A(A,B) ((uint8) (A)) + #define Blend_B(A,B) ((uint8) (B)) + + + long LoadPng (LPCTSTR FileName, HBITMAP & hbmp); // load a PNG file into a bitmap Index: xml_load_world.cpp =================================================================== RCS file: /cvs/mushclient/xml_load_world.cpp,v retrieving revision 1.93 retrieving revision 1.94 diff -c -r1.93 -r1.94 *** xml_load_world.cpp 6 Jul 2008 03:41:06 -0000 1.93 --- xml_load_world.cpp 26 Aug 2008 05:23:14 -0000 1.94 *************** *** 458,463 **** --- 458,466 ---- = m_CurrentPlugin->GetPluginDispid (ON_PLUGIN_PARTIAL_LINE); m_CurrentPlugin->m_dispid_plugin_telnet_option = m_CurrentPlugin->GetPluginDispid (ON_PLUGIN_TELNET_OPTION); + m_CurrentPlugin->m_dispid_plugin_on_world_output_resized + = m_CurrentPlugin->GetPluginDispid (ON_PLUGIN_WORLD_OUTPUT_RESIZED); + m_CurrentPlugin->m_dispid_plugin_OnMXP_Start = m_CurrentPlugin->GetPluginDispid (ON_PLUGIN_MXP_START ); Index: install/readme.txt =================================================================== RCS file: /cvs/mushclient/install/readme.txt,v retrieving revision 1.180 retrieving revision 1.182 diff -c -r1.180 -r1.182 *** install/readme.txt 6 Aug 2008 02:35:28 -0000 1.180 --- install/readme.txt 29 Aug 2008 03:35:05 -0000 1.182 *************** *** 1,7 **** ! MUSHclient version 4.35 ======================= ! Wednesday, 6th August 2008 Author: Nick Gammon Web support: http://www.gammon.com.au/forum/ --- 1,7 ---- ! MUSHclient version 4.36 ======================= ! Friday, 29th August 2008 Author: Nick Gammon Web support: http://www.gammon.com.au/forum/