From 796be733b374beb5660ee2713fc28c4e69331cbd Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Thu, 26 Sep 2013 16:17:54 -0700
Subject: ACME-946 : Do not force set the focus on the web element, that messes
 things up badly...

---
 indra/newview/llfloaterwebcontent.cpp | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp
index 9d703d2752..5c569b9bf0 100755
--- a/indra/newview/llfloaterwebcontent.cpp
+++ b/indra/newview/llfloaterwebcontent.cpp
@@ -253,11 +253,6 @@ void LLFloaterWebContent::open_media(const Params& p)
 	getChildView("address")->setEnabled(address_entry_enabled);
 	getChildView("popexternal")->setEnabled(address_entry_enabled);
 
-	if (!address_entry_enabled)
-	{
-		mWebBrowser->setFocus(TRUE);
-	}
-
 	if (!p.show_chrome)
 	{
 		setResizeLimits(100, 100);
@@ -434,9 +429,6 @@ void LLFloaterWebContent::set_current_url(const std::string& url)
         mAddressCombo->remove(mCurrentURL);
         mAddressCombo->add(mDisplayURL);
         mAddressCombo->selectByValue(mDisplayURL);
-
-        // Set the focus back to the web page. When setting the url, there's no point to leave the focus anywhere else.
-		mWebBrowser->setFocus(TRUE);
     }
 }
 
-- 
cgit v1.2.3


From 528f424952ea77945139279c7de4bb67880ce169 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Wed, 9 Oct 2013 00:32:31 +0100
Subject: temporarily added test call for FlickrConnect and TwitterConnect for
 ACME-1014

---
 indra/newview/llfacebookconnect.cpp | 29 +++++++++++++++++++++++++++++
 indra/newview/llfacebookconnect.h   |  4 ++++
 indra/newview/llviewerregion.cpp    |  3 ++-
 3 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index 611d18d6d6..497354acc7 100644
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -366,6 +366,30 @@ std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, b
 	return url;
 }
 
+std::string LLFacebookConnect::getFlickrConnectURL(const std::string& route, bool include_read_from_master)
+{
+	std::string url = gAgent.getRegion()->getCapability("FlickrConnect");
+	url += route;
+    
+	if (include_read_from_master && mReadFromMaster)
+	{
+		url += "?read_from_master=true";
+	}
+	return url;
+}
+
+std::string LLFacebookConnect::getTwitterConnectURL(const std::string& route, bool include_read_from_master)
+{
+	std::string url = gAgent.getRegion()->getCapability("TwitterConnect");
+	url += route;
+    
+	if (include_read_from_master && mReadFromMaster)
+	{
+		url += "?read_from_master=true";
+	}
+	return url;
+}
+
 void LLFacebookConnect::connectToFacebook(const std::string& auth_code, const std::string& auth_state)
 {
 	LLSD body;
@@ -388,6 +412,11 @@ void LLFacebookConnect::checkConnectionToFacebook(bool auto_connect)
 	const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
 	LLHTTPClient::get(getFacebookConnectURL("/connection", true), new LLFacebookConnectedResponder(auto_connect),
 						LLSD(), timeout, follow_redirects);
+	
+	// TEMPORARY FOR TESTING - CHO
+	llinfos << "FlickrConnect URL: " << getFlickrConnectURL() << LL_ENDL;
+	llinfos << "TwitterConnect URL: " << getTwitterConnectURL() << LL_ENDL;
+
 }
 
 void LLFacebookConnect::loadFacebookInfo()
diff --git a/indra/newview/llfacebookconnect.h b/indra/newview/llfacebookconnect.h
index a77ac24167..c4117174c1 100644
--- a/indra/newview/llfacebookconnect.h
+++ b/indra/newview/llfacebookconnect.h
@@ -89,6 +89,10 @@ private:
 	LLFacebookConnect();
 	~LLFacebookConnect() {};
  	std::string getFacebookConnectURL(const std::string& route = "", bool include_read_from_master = false);
+
+	// TEMPORARY FOR TESTING - CHO
+ 	std::string getFlickrConnectURL(const std::string& route = "", bool include_read_from_master = false);
+ 	std::string getTwitterConnectURL(const std::string& route = "", bool include_read_from_master = false);
    
     EConnectionState mConnectionState;
 	BOOL mConnected;
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 460f9084d9..02402fa876 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1596,7 +1596,8 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 	capabilityNames.append("EstateChangeInfo");
 	capabilityNames.append("EventQueueGet");
 	capabilityNames.append("FacebookConnect");
-	//capabilityNames.append("FacebookRedirect");
+	capabilityNames.append("FlickrConnect");
+	capabilityNames.append("TwitterConnect");
 
 	if (gSavedSettings.getBOOL("UseHTTPInventory"))
 	{
-- 
cgit v1.2.3


From 542864f8ea9bb5602ac76553d76898178ad79d0f Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 29 Oct 2013 12:02:40 -0700
Subject: ACME-1099 : Prevent possible crashes on get connect URL for Twitter
 and Flickr

---
 indra/newview/llfacebookconnect.cpp | 48 +++++++++++++++++++++++++++----------
 1 file changed, 36 insertions(+), 12 deletions(-)

diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index 67a1792aa5..f82c5a05a0 100644
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -373,25 +373,35 @@ std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, b
 
 std::string LLFacebookConnect::getFlickrConnectURL(const std::string& route, bool include_read_from_master)
 {
-	std::string url = gAgent.getRegion()->getCapability("FlickrConnect");
-	url += route;
+    std::string url("");
+    LLViewerRegion *regionp = gAgent.getRegion();
+    if (regionp)
+    {
+        url = regionp->getCapability("FlickrConnect");
+        url += route;
     
-	if (include_read_from_master && mReadFromMaster)
-	{
-		url += "?read_from_master=true";
-	}
+        if (include_read_from_master && mReadFromMaster)
+        {
+            url += "?read_from_master=true";
+        }
+    }
 	return url;
 }
 
 std::string LLFacebookConnect::getTwitterConnectURL(const std::string& route, bool include_read_from_master)
 {
-	std::string url = gAgent.getRegion()->getCapability("TwitterConnect");
-	url += route;
+    std::string url("");
+    LLViewerRegion *regionp = gAgent.getRegion();
+    if (regionp)
+    {
+        url = regionp->getCapability("TwitterConnect");
+        url += route;
     
-	if (include_read_from_master && mReadFromMaster)
-	{
-		url += "?read_from_master=true";
-	}
+        if (include_read_from_master && mReadFromMaster)
+        {
+            url += "?read_from_master=true";
+        }
+    }
 	return url;
 }
 
@@ -399,9 +409,13 @@ void LLFacebookConnect::connectToFacebook(const std::string& auth_code, const st
 {
 	LLSD body;
 	if (!auth_code.empty())
+    {
 		body["code"] = auth_code;
+    }
 	if (!auth_state.empty())
+    {
 		body["state"] = auth_state;
+    }
     
 	LLHTTPClient::put(getFacebookConnectURL("/connection"), body, new LLFacebookConnectResponder());
 }
@@ -450,15 +464,25 @@ void LLFacebookConnect::postCheckin(const std::string& location, const std::stri
 {
 	LLSD body;
 	if (!location.empty())
+    {
 		body["location"] = location;
+    }
 	if (!name.empty())
+    {
 		body["name"] = name;
+    }
 	if (!description.empty())
+    {
 		body["description"] = description;
+    }
 	if (!image.empty())
+    {
 		body["image"] = image;
+    }
 	if (!message.empty())
+    {
 		body["message"] = message;
+    }
 
 	// Note: we can use that route for different publish action. We should be able to use the same responder.
 	LLHTTPClient::post(getFacebookConnectURL("/share/checkin", true), body, new LLFacebookShareResponder());
-- 
cgit v1.2.3


From a52fba0e48d28c3a3d40302192cd1eaef393e96f Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 30 Oct 2013 16:12:02 -0700
Subject: ACME-1104 : Crash when getting a cap from an unset region. Extended
 ACME-1099 fix.

---
 indra/newview/llfacebookconnect.cpp | 34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index 67a1792aa5..18a817f371 100644
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -373,25 +373,35 @@ std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, b
 
 std::string LLFacebookConnect::getFlickrConnectURL(const std::string& route, bool include_read_from_master)
 {
-	std::string url = gAgent.getRegion()->getCapability("FlickrConnect");
-	url += route;
+    std::string url("");
+    LLViewerRegion *regionp = gAgent.getRegion();
+    if (regionp)
+    {
+        url = regionp->getCapability("FlickrConnect");
+        url += route;
     
-	if (include_read_from_master && mReadFromMaster)
-	{
-		url += "?read_from_master=true";
-	}
+        if (include_read_from_master && mReadFromMaster)
+        {
+            url += "?read_from_master=true";
+        }
+    }
 	return url;
 }
 
 std::string LLFacebookConnect::getTwitterConnectURL(const std::string& route, bool include_read_from_master)
 {
-	std::string url = gAgent.getRegion()->getCapability("TwitterConnect");
-	url += route;
+    std::string url("");
+    LLViewerRegion *regionp = gAgent.getRegion();
+    if (regionp)
+    {
+        url = regionp->getCapability("TwitterConnect");
+        url += route;
     
-	if (include_read_from_master && mReadFromMaster)
-	{
-		url += "?read_from_master=true";
-	}
+        if (include_read_from_master && mReadFromMaster)
+        {
+            url += "?read_from_master=true";
+        }
+    }
 	return url;
 }
 
-- 
cgit v1.2.3


From 1b8b6e76bf175c4d0ead8d3fc6f01558066cbec9 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Fri, 1 Nov 2013 20:47:28 +0100
Subject: added LLFlickrConnect for ACME-1116

---
 indra/newview/CMakeLists.txt                       |   2 +
 indra/newview/llfacebookconnect.cpp                |  47 +-
 indra/newview/llfacebookconnect.h                  |   4 -
 indra/newview/llflickrconnect.cpp                  | 509 +++++++++++++++++++++
 indra/newview/llflickrconnect.h                    |  98 ++++
 .../newview/skins/default/xui/en/notifications.xml |   9 +-
 indra/newview/skins/default/xui/en/strings.xml     |   3 +
 7 files changed, 624 insertions(+), 48 deletions(-)
 create mode 100644 indra/newview/llflickrconnect.cpp
 create mode 100644 indra/newview/llflickrconnect.h

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 1fea6dea9f..6f5deb639c 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -199,6 +199,7 @@ set(viewer_SOURCE_FILES
     llfilteredwearablelist.cpp
     llfirstuse.cpp
     llflexibleobject.cpp
+    llflickrconnect.cpp
     llfloaterabout.cpp
     llfloaterbvhpreview.cpp
     llfloaterauction.cpp
@@ -787,6 +788,7 @@ set(viewer_HEADER_FILES
     llfilteredwearablelist.h
     llfirstuse.h
     llflexibleobject.h
+    llflickrconnect.h
     llfloaterabout.h
     llfloaterbvhpreview.h
     llfloaterauction.h
diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index 18a817f371..2434272ef7 100644
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -58,7 +58,7 @@ void log_facebook_connect_error(const std::string& request, U32 status, const st
     }
 }
 
-void toast_user_for_success()
+void toast_user_for_facebook_success()
 {
 	LLSD args;
     args["MESSAGE"] = LLTrans::getString("facebook_post_success");
@@ -74,9 +74,9 @@ public:
     
 	bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
 	{
-		if (tokens.size() > 0)
+		if (tokens.size() >= 2)
 		{
-			if (tokens[0].asString() == "connect")
+			if (tokens[0].asString() == "connect" && tokens[1].asString() == "facebook")
 			{
 				// this command probably came from the fbc_web browser, so close it
 				LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web");
@@ -150,7 +150,7 @@ public:
 	{
 		if (isGoodStatus(status))
 		{
-            toast_user_for_success();
+            toast_user_for_facebook_success();
 			LL_DEBUGS("FacebookConnect") << "Post successful. content: " << content << LL_ENDL;
 			
 			LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POSTED);
@@ -371,40 +371,6 @@ std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, b
 	return url;
 }
 
-std::string LLFacebookConnect::getFlickrConnectURL(const std::string& route, bool include_read_from_master)
-{
-    std::string url("");
-    LLViewerRegion *regionp = gAgent.getRegion();
-    if (regionp)
-    {
-        url = regionp->getCapability("FlickrConnect");
-        url += route;
-    
-        if (include_read_from_master && mReadFromMaster)
-        {
-            url += "?read_from_master=true";
-        }
-    }
-	return url;
-}
-
-std::string LLFacebookConnect::getTwitterConnectURL(const std::string& route, bool include_read_from_master)
-{
-    std::string url("");
-    LLViewerRegion *regionp = gAgent.getRegion();
-    if (regionp)
-    {
-        url = regionp->getCapability("TwitterConnect");
-        url += route;
-    
-        if (include_read_from_master && mReadFromMaster)
-        {
-            url += "?read_from_master=true";
-        }
-    }
-	return url;
-}
-
 void LLFacebookConnect::connectToFacebook(const std::string& auth_code, const std::string& auth_state)
 {
 	LLSD body;
@@ -427,11 +393,6 @@ void LLFacebookConnect::checkConnectionToFacebook(bool auto_connect)
 	const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
 	LLHTTPClient::get(getFacebookConnectURL("/connection", true), new LLFacebookConnectedResponder(auto_connect),
 						LLSD(), timeout, follow_redirects);
-	
-	// TEMPORARY FOR TESTING - CHO
-	llinfos << "FlickrConnect URL: " << getFlickrConnectURL() << LL_ENDL;
-	llinfos << "TwitterConnect URL: " << getTwitterConnectURL() << LL_ENDL;
-
 }
 
 void LLFacebookConnect::loadFacebookInfo()
diff --git a/indra/newview/llfacebookconnect.h b/indra/newview/llfacebookconnect.h
index c4117174c1..c157db2178 100644
--- a/indra/newview/llfacebookconnect.h
+++ b/indra/newview/llfacebookconnect.h
@@ -90,10 +90,6 @@ private:
 	~LLFacebookConnect() {};
  	std::string getFacebookConnectURL(const std::string& route = "", bool include_read_from_master = false);
 
-	// TEMPORARY FOR TESTING - CHO
- 	std::string getFlickrConnectURL(const std::string& route = "", bool include_read_from_master = false);
- 	std::string getTwitterConnectURL(const std::string& route = "", bool include_read_from_master = false);
-   
     EConnectionState mConnectionState;
 	BOOL mConnected;
 	LLSD mInfo;
diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp
new file mode 100644
index 0000000000..ba9be3af24
--- /dev/null
+++ b/indra/newview/llflickrconnect.cpp
@@ -0,0 +1,509 @@
+/** 
+ * @file llflickrconnect.h
+ * @author Merov, Cho
+ * @brief Connection to Flickr Service
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llflickrconnect.h"
+
+#include "llagent.h"
+#include "llcallingcard.h"			// for LLAvatarTracker
+#include "llcommandhandler.h"
+#include "llhttpclient.h"
+#include "llnotificationsutil.h"
+#include "llurlaction.h"
+#include "llimagepng.h"
+#include "llimagejpeg.h"
+#include "lltrans.h"
+#include "llevents.h"
+#include "llviewerregion.h"
+
+#include "llfloaterwebcontent.h"
+#include "llfloaterreg.h"
+
+boost::scoped_ptr<LLEventPump> LLFlickrConnect::sStateWatcher(new LLEventStream("FlickrConnectState"));
+boost::scoped_ptr<LLEventPump> LLFlickrConnect::sInfoWatcher(new LLEventStream("FlickrConnectInfo"));
+boost::scoped_ptr<LLEventPump> LLFlickrConnect::sContentWatcher(new LLEventStream("FlickrConnectContent"));
+
+// Local functions
+void log_flickr_connect_error(const std::string& request, U32 status, const std::string& reason, const std::string& code, const std::string& description)
+{
+    // Note: 302 (redirect) is *not* an error that warrants logging
+    if (status != 302)
+    {
+		LL_WARNS("FlickrConnect") << request << " request failed with a " << status << " " << reason << ". Reason: " << code << " (" << description << ")" << LL_ENDL;
+    }
+}
+
+void toast_user_for_flickr_success()
+{
+	LLSD args;
+    args["MESSAGE"] = LLTrans::getString("flickr_post_success");
+    LLNotificationsUtil::add("FlickrConnect", args);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+class LLFlickrConnectHandler : public LLCommandHandler
+{
+public:
+	LLFlickrConnectHandler() : LLCommandHandler("fbc", UNTRUSTED_THROTTLE) { }
+    
+	bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
+	{
+		if (tokens.size() >= 2)
+		{
+			if (tokens[0].asString() == "connect" && tokens[1].asString() == "flickr")
+			{
+				// this command probably came from the fbc_web browser, so close it
+				LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web");
+				if (fbc_web)
+				{
+					fbc_web->closeFloater();
+				}
+
+				// connect to flickr
+				if (query_map.has("oauth_token"))
+				{
+                    LLFlickrConnect::instance().connectToFlickr(query_map["oauth_token"], query_map.get("oauth_verifier"));
+				}
+				return true;
+			}
+		}
+		return false;
+	}
+};
+LLFlickrConnectHandler gFlickrConnectHandler;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+class LLFlickrConnectResponder : public LLHTTPClient::Responder
+{
+	LOG_CLASS(LLFlickrConnectResponder);
+public:
+	
+    LLFlickrConnectResponder()
+    {
+        LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS);
+    }
+    
+	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	{
+		if (isGoodStatus(status))
+		{
+			LL_DEBUGS("FlickrConnect") << "Connect successful. content: " << content << LL_ENDL;
+			
+            LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTED);
+		}
+		else if (status != 302)
+		{
+            LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
+            log_flickr_connect_error("Connect", status, reason, content.get("error_code"), content.get("error_description"));
+		}
+	}
+    
+    void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+    {
+        if (status == 302)
+        {
+            LLFlickrConnect::instance().openFlickrWeb(content["location"]);
+        }
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+class LLFlickrShareResponder : public LLHTTPClient::Responder
+{
+	LOG_CLASS(LLFlickrShareResponder);
+public:
+    
+	LLFlickrShareResponder()
+	{
+		LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_POSTING);
+	}
+	
+	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	{
+		if (isGoodStatus(status))
+		{
+            toast_user_for_flickr_success();
+			LL_DEBUGS("FlickrConnect") << "Post successful. content: " << content << LL_ENDL;
+			
+			LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_POSTED);
+		}
+		else if (status == 404)
+		{
+			LLFlickrConnect::instance().connectToFlickr();
+		}
+		else
+		{
+            LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_POST_FAILED);
+            log_flickr_connect_error("Share", status, reason, content.get("error_code"), content.get("error_description"));
+		}
+	}
+    
+    void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+    {
+        if (status == 302)
+        {
+            LLFlickrConnect::instance().openFlickrWeb(content["location"]);
+        }
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+class LLFlickrDisconnectResponder : public LLHTTPClient::Responder
+{
+	LOG_CLASS(LLFlickrDisconnectResponder);
+public:
+ 
+	LLFlickrDisconnectResponder()
+	{
+		LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_DISCONNECTING);
+	}
+
+	void setUserDisconnected()
+	{
+		// Clear data
+		LLFlickrConnect::instance().clearInfo();
+
+		//Notify state change
+		LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_NOT_CONNECTED);
+	}
+
+	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	{
+		if (isGoodStatus(status)) 
+		{
+			LL_DEBUGS("FlickrConnect") << "Disconnect successful. content: " << content << LL_ENDL;
+			setUserDisconnected();
+
+		}
+		//User not found so already disconnected
+		else if(status == 404)
+		{
+			LL_DEBUGS("FlickrConnect") << "Already disconnected. content: " << content << LL_ENDL;
+			setUserDisconnected();
+		}
+		else
+		{
+			LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_DISCONNECT_FAILED);
+            log_flickr_connect_error("Disconnect", status, reason, content.get("error_code"), content.get("error_description"));
+		}
+	}
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+class LLFlickrConnectedResponder : public LLHTTPClient::Responder
+{
+	LOG_CLASS(LLFlickrConnectedResponder);
+public:
+    
+	LLFlickrConnectedResponder(bool auto_connect) : mAutoConnect(auto_connect)
+    {
+		LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS);
+    }
+    
+	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	{
+		if (isGoodStatus(status))
+		{
+			LL_DEBUGS("FlickrConnect") << "Connect successful. content: " << content << LL_ENDL;
+            
+            LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTED);
+		}
+		else
+		{
+			// show the flickr login page if not connected yet
+			if (status == 404)
+			{
+				if (mAutoConnect)
+				{
+					LLFlickrConnect::instance().connectToFlickr();
+				}
+				else
+				{
+					LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_NOT_CONNECTED);
+				}
+			}
+            else
+            {
+                LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
+				log_flickr_connect_error("Connected", status, reason, content.get("error_code"), content.get("error_description"));
+            }
+		}
+	}
+    
+private:
+	bool mAutoConnect;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+class LLFlickrInfoResponder : public LLHTTPClient::Responder
+{
+	LOG_CLASS(LLFlickrInfoResponder);
+public:
+
+	virtual void completed(U32 status, const std::string& reason, const LLSD& info)
+	{
+		if (isGoodStatus(status))
+		{
+			llinfos << "Flickr: Info received" << llendl;
+			LL_DEBUGS("FlickrConnect") << "Getting Flickr info successful. info: " << info << LL_ENDL;
+			LLFlickrConnect::instance().storeInfo(info);
+		}
+		else
+		{
+			log_flickr_connect_error("Info", status, reason, info.get("error_code"), info.get("error_description"));
+		}
+	}
+
+	void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+	{
+		if (status == 302)
+		{
+			LLFlickrConnect::instance().openFlickrWeb(content["location"]);
+		}
+	}
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+LLFlickrConnect::LLFlickrConnect()
+:	mConnectionState(FLICKR_NOT_CONNECTED),
+	mConnected(false),
+	mInfo(),
+	mRefreshInfo(false),
+	mReadFromMaster(false)
+{
+}
+
+void LLFlickrConnect::openFlickrWeb(std::string url)
+{
+	// Open the URL in an internal browser window without navigation UI
+	LLFloaterWebContent::Params p;
+    p.url(url).show_chrome(true);
+    p.url(url).allow_address_entry(false);
+    p.url(url).allow_back_forward_navigation(false);
+    p.url(url).trusted_content(true);
+	LLFloater *floater = LLFloaterReg::showInstance("fbc_web", p);
+	//the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems).
+	//So when showing the internal web browser, set focus to it's containing floater "fbc_web". When a mouse event 
+	//occurs on the "webbrowser" panel part of the floater, a mouse cursor will properly show and the "webbrowser" will gain focus.
+	//fbc_web floater contains the "webbrowser" panel.    JIRA: ACME-744
+	gFocusMgr.setKeyboardFocus( floater );
+
+	//LLUrlAction::openURLExternal(url);
+}
+
+std::string LLFlickrConnect::getFlickrConnectURL(const std::string& route, bool include_read_from_master)
+{
+    std::string url("");
+    LLViewerRegion *regionp = gAgent.getRegion();
+    if (regionp)
+    {
+        url = regionp->getCapability("FlickrConnect");
+        url += route;
+    
+        if (include_read_from_master && mReadFromMaster)
+        {
+            url += "?read_from_master=true";
+        }
+    }
+	return url;
+}
+
+void LLFlickrConnect::connectToFlickr(const std::string& request_token, const std::string& oauth_verifier)
+{
+	LLSD body;
+	if (!request_token.empty())
+		body["request_token"] = request_token;
+	if (!oauth_verifier.empty())
+		body["oauth_verifier"] = oauth_verifier;
+    
+	LLHTTPClient::put(getFlickrConnectURL("/connection"), body, new LLFlickrConnectResponder());
+}
+
+void LLFlickrConnect::disconnectFromFlickr()
+{
+	LLHTTPClient::del(getFlickrConnectURL("/connection"), new LLFlickrDisconnectResponder());
+}
+
+void LLFlickrConnect::checkConnectionToFlickr(bool auto_connect)
+{
+	const bool follow_redirects = false;
+	const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	LLHTTPClient::get(getFlickrConnectURL("/connection", true), new LLFlickrConnectedResponder(auto_connect),
+						LLSD(), timeout, follow_redirects);
+}
+
+void LLFlickrConnect::loadFlickrInfo()
+{
+	if(mRefreshInfo)
+	{
+		const bool follow_redirects = false;
+		const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+		LLHTTPClient::get(getFlickrConnectURL("/info", true), new LLFlickrInfoResponder(),
+			LLSD(), timeout, follow_redirects);
+	}
+}
+
+void LLFlickrConnect::uploadPhoto(const std::string& image_url, const std::string& title, const std::string& description, const std::string& tags, int safety_level)
+{
+	LLSD body;
+	body["image"] = image_url;
+	body["title"] = title;
+	body["description"] = description;
+	body["tags"] = tags;
+	body["safety_level"] = safety_level;
+	
+    // Note: we can use that route for different publish action. We should be able to use the same responder.
+	LLHTTPClient::post(getFlickrConnectURL("/share/photo", true), body, new LLFlickrShareResponder());
+}
+
+void LLFlickrConnect::uploadPhoto(LLPointer<LLImageFormatted> image, const std::string& title, const std::string& description, const std::string& tags, int safety_level)
+{
+	std::string imageFormat;
+	if (dynamic_cast<LLImagePNG*>(image.get()))
+	{
+		imageFormat = "png";
+	}
+	else if (dynamic_cast<LLImageJPEG*>(image.get()))
+	{
+		imageFormat = "jpg";
+	}
+	else
+	{
+		llwarns << "Image to upload is not a PNG or JPEG" << llendl;
+		return;
+	}
+	
+	// All this code is mostly copied from LLWebProfile::post()
+	const std::string boundary = "----------------------------0123abcdefab";
+
+	LLSD headers;
+	headers["Content-Type"] = "multipart/form-data; boundary=" + boundary;
+
+	std::ostringstream body;
+
+	// *NOTE: The order seems to matter.
+	body	<< "--" << boundary << "\r\n"
+			<< "Content-Disposition: form-data; name=\"title\"\r\n\r\n"
+			<< title << "\r\n";
+
+	body	<< "--" << boundary << "\r\n"
+			<< "Content-Disposition: form-data; name=\"description\"\r\n\r\n"
+			<< description << "\r\n";
+
+	body	<< "--" << boundary << "\r\n"
+			<< "Content-Disposition: form-data; name=\"tags\"\r\n\r\n"
+			<< tags << "\r\n";
+
+	body	<< "--" << boundary << "\r\n"
+			<< "Content-Disposition: form-data; name=\"safety_level\"\r\n\r\n"
+			<< safety_level << "\r\n";
+
+	body	<< "--" << boundary << "\r\n"
+			<< "Content-Disposition: form-data; name=\"image\"; filename=\"snapshot." << imageFormat << "\"\r\n"
+			<< "Content-Type: image/" << imageFormat << "\r\n\r\n";
+
+	// Insert the image data.
+	// *FIX: Treating this as a string will probably screw it up ...
+	U8* image_data = image->getData();
+	for (S32 i = 0; i < image->getDataSize(); ++i)
+	{
+		body << image_data[i];
+	}
+
+	body <<	"\r\n--" << boundary << "--\r\n";
+
+	// postRaw() takes ownership of the buffer and releases it later.
+	size_t size = body.str().size();
+	U8 *data = new U8[size];
+	memcpy(data, body.str().data(), size);
+	
+    // Note: we can use that route for different publish action. We should be able to use the same responder.
+	LLHTTPClient::postRaw(getFlickrConnectURL("/share/photo", true), data, size, new LLFlickrShareResponder(), headers);
+}
+
+void LLFlickrConnect::storeInfo(const LLSD& info)
+{
+	mInfo = info;
+	mRefreshInfo = false;
+
+	sInfoWatcher->post(info);
+}
+
+const LLSD& LLFlickrConnect::getInfo() const
+{
+	return mInfo;
+}
+
+void LLFlickrConnect::clearInfo()
+{
+	mInfo = LLSD();
+}
+
+void LLFlickrConnect::setDataDirty()
+{
+	mRefreshInfo = true;
+}
+
+void LLFlickrConnect::setConnectionState(LLFlickrConnect::EConnectionState connection_state)
+{
+	if(connection_state == FLICKR_CONNECTED)
+	{
+		mReadFromMaster = true;
+		setConnected(true);
+		setDataDirty();
+	}
+	else if(connection_state == FLICKR_NOT_CONNECTED)
+	{
+		setConnected(false);
+	}
+	else if(connection_state == FLICKR_POSTED)
+	{
+		mReadFromMaster = false;
+	}
+
+	if (mConnectionState != connection_state)
+	{
+		LLSD state_info;
+		state_info["enum"] = connection_state;
+		sStateWatcher->post(state_info);
+	}
+	
+	mConnectionState = connection_state;
+}
+
+void LLFlickrConnect::setConnected(bool connected)
+{
+	mConnected = connected;
+}
diff --git a/indra/newview/llflickrconnect.h b/indra/newview/llflickrconnect.h
new file mode 100644
index 0000000000..b127e6e104
--- /dev/null
+++ b/indra/newview/llflickrconnect.h
@@ -0,0 +1,98 @@
+/** 
+ * @file llflickrconnect.h
+ * @author Merov, Cho
+ * @brief Connection to Flickr Service
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLICKRCONNECT_H
+#define LL_LLFLICKRCONNECT_H
+
+#include "llsingleton.h"
+#include "llimage.h"
+
+class LLEventPump;
+
+/**
+ * @class LLFlickrConnect
+ *
+ * Manages authentication to, and interaction with, a web service allowing the
+ * the viewer to upload photos to Flickr.
+ */
+class LLFlickrConnect : public LLSingleton<LLFlickrConnect>
+{
+	LOG_CLASS(LLFlickrConnect);
+public:
+    enum EConnectionState
+	{
+		FLICKR_NOT_CONNECTED = 0,
+		FLICKR_CONNECTION_IN_PROGRESS = 1,
+		FLICKR_CONNECTED = 2,
+		FLICKR_CONNECTION_FAILED = 3,
+		FLICKR_POSTING = 4,
+		FLICKR_POSTED = 5,
+		FLICKR_POST_FAILED = 6,
+		FLICKR_DISCONNECTING = 7,
+		FLICKR_DISCONNECT_FAILED = 8
+	};
+	
+	void connectToFlickr(const std::string& request_token = "", const std::string& oauth_verifier = "");	// Initiate the complete Flickr connection. Please use checkConnectionToFlickr() in normal use.
+	void disconnectFromFlickr();																			// Disconnect from the Flickr service.
+    void checkConnectionToFlickr(bool auto_connect = false);												// Check if an access token is available on the Flickr service. If not, call connectToFlickr().
+    
+	void loadFlickrInfo();
+	void uploadPhoto(const std::string& image_url, const std::string& title, const std::string& description, const std::string& tags, int safety_level);
+	void uploadPhoto(LLPointer<LLImageFormatted> image, const std::string& title, const std::string& description, const std::string& tags, int safety_level);
+	
+	void storeInfo(const LLSD& info);
+	const LLSD& getInfo() const;
+	void clearInfo();
+	void setDataDirty();
+    
+    void setConnectionState(EConnectionState connection_state);
+	void setConnected(bool connected);
+	bool isConnected() { return mConnected; }
+	bool isTransactionOngoing() { return ((mConnectionState == FLICKR_CONNECTION_IN_PROGRESS) || (mConnectionState == FLICKR_POSTING) || (mConnectionState == FLICKR_DISCONNECTING)); }
+    EConnectionState getConnectionState() { return mConnectionState; }
+    
+    void openFlickrWeb(std::string url);
+
+private:
+	friend class LLSingleton<LLFlickrConnect>;
+
+	LLFlickrConnect();
+	~LLFlickrConnect() {};
+ 	std::string getFlickrConnectURL(const std::string& route = "", bool include_read_from_master = false);
+
+    EConnectionState mConnectionState;
+	BOOL mConnected;
+	LLSD mInfo;
+	bool mRefreshInfo;
+	bool mReadFromMaster;
+	
+	static boost::scoped_ptr<LLEventPump> sStateWatcher;
+	static boost::scoped_ptr<LLEventPump> sInfoWatcher;
+	static boost::scoped_ptr<LLEventPump> sContentWatcher;
+};
+
+#endif // LL_LLFLICKRCONNECT_H
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index e7c89db069..b562c5cb5e 100755
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -6044,7 +6044,14 @@ Please select at least one type of content to search (General, Moderate, or Adul
   type="notifytip">
 [MESSAGE]
  </notification>
-    
+
+  <notification
+   icon="notify.tga"
+   name="FlickrConnect"
+   type="notifytip">
+    [MESSAGE]
+  </notification>
+
   <notification
    icon="notify.tga"
    name="PaymentReceived"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 8ac95beddb..0d2083632d 100755
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3442,6 +3442,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
   <string name="facebook_post_success">
     You posted to Facebook.
   </string>
+  <string name="flickr_post_success">
+    You posted to Flickr.
+  </string>
 
   <string name="no_session_message">
     (IM Session Doesn't Exist)
-- 
cgit v1.2.3


From 963c97f64a4d1490fe8380805c4de38598adddad Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Fri, 1 Nov 2013 23:12:45 +0100
Subject: added LLTwitterConnect for ACME-1133

---
 indra/newview/CMakeLists.txt                       |   2 +
 indra/newview/lltwitterconnect.cpp                 | 503 +++++++++++++++++++++
 indra/newview/lltwitterconnect.h                   |  99 ++++
 .../newview/skins/default/xui/en/notifications.xml |   7 +
 indra/newview/skins/default/xui/en/strings.xml     |   3 +
 5 files changed, 614 insertions(+)
 create mode 100644 indra/newview/lltwitterconnect.cpp
 create mode 100644 indra/newview/lltwitterconnect.h

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 6f5deb639c..ac2d3f8ff4 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -568,6 +568,7 @@ set(viewer_SOURCE_FILES
     lltransientdockablefloater.cpp
     lltransientfloatermgr.cpp
     lltranslate.cpp
+    lltwitterconnect.cpp
     lluilistener.cpp
     lluploaddialog.cpp
     lluploadfloaterobservers.cpp
@@ -1147,6 +1148,7 @@ set(viewer_HEADER_FILES
     lltransientdockablefloater.h
     lltransientfloatermgr.h
     lltranslate.h
+    lltwitterconnect.h
     lluiconstants.h
     lluilistener.h
     lluploaddialog.h
diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp
new file mode 100644
index 0000000000..6efcce8127
--- /dev/null
+++ b/indra/newview/lltwitterconnect.cpp
@@ -0,0 +1,503 @@
+/** 
+ * @file lltwitterconnect.h
+ * @author Merov, Cho
+ * @brief Connection to Twitter Service
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltwitterconnect.h"
+
+#include "llagent.h"
+#include "llcallingcard.h"			// for LLAvatarTracker
+#include "llcommandhandler.h"
+#include "llhttpclient.h"
+#include "llnotificationsutil.h"
+#include "llurlaction.h"
+#include "llimagepng.h"
+#include "llimagejpeg.h"
+#include "lltrans.h"
+#include "llevents.h"
+#include "llviewerregion.h"
+
+#include "llfloaterwebcontent.h"
+#include "llfloaterreg.h"
+
+boost::scoped_ptr<LLEventPump> LLTwitterConnect::sStateWatcher(new LLEventStream("TwitterConnectState"));
+boost::scoped_ptr<LLEventPump> LLTwitterConnect::sInfoWatcher(new LLEventStream("TwitterConnectInfo"));
+boost::scoped_ptr<LLEventPump> LLTwitterConnect::sContentWatcher(new LLEventStream("TwitterConnectContent"));
+
+// Local functions
+void log_twitter_connect_error(const std::string& request, U32 status, const std::string& reason, const std::string& code, const std::string& description)
+{
+    // Note: 302 (redirect) is *not* an error that warrants logging
+    if (status != 302)
+    {
+		LL_WARNS("TwitterConnect") << request << " request failed with a " << status << " " << reason << ". Reason: " << code << " (" << description << ")" << LL_ENDL;
+    }
+}
+
+void toast_user_for_twitter_success()
+{
+	LLSD args;
+    args["MESSAGE"] = LLTrans::getString("twitter_post_success");
+    LLNotificationsUtil::add("TwitterConnect", args);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+class LLTwitterConnectHandler : public LLCommandHandler
+{
+public:
+	LLTwitterConnectHandler() : LLCommandHandler("fbc", UNTRUSTED_THROTTLE) { }
+    
+	bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
+	{
+		if (tokens.size() >= 2)
+		{
+			if (tokens[0].asString() == "connect" && tokens[1].asString() == "twitter")
+			{
+				// this command probably came from the fbc_web browser, so close it
+				LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web");
+				if (fbc_web)
+				{
+					fbc_web->closeFloater();
+				}
+
+				// connect to twitter
+				if (query_map.has("oauth_token"))
+				{
+                    LLTwitterConnect::instance().connectToTwitter(query_map["oauth_token"], query_map.get("oauth_verifier"));
+				}
+				return true;
+			}
+		}
+		return false;
+	}
+};
+LLTwitterConnectHandler gTwitterConnectHandler;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+class LLTwitterConnectResponder : public LLHTTPClient::Responder
+{
+	LOG_CLASS(LLTwitterConnectResponder);
+public:
+	
+    LLTwitterConnectResponder()
+    {
+        LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS);
+    }
+    
+	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	{
+		if (isGoodStatus(status))
+		{
+			LL_DEBUGS("TwitterConnect") << "Connect successful. content: " << content << LL_ENDL;
+			
+            LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTED);
+		}
+		else if (status != 302)
+		{
+            LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
+            log_twitter_connect_error("Connect", status, reason, content.get("error_code"), content.get("error_description"));
+		}
+	}
+    
+    void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+    {
+        if (status == 302)
+        {
+            LLTwitterConnect::instance().openTwitterWeb(content["location"]);
+        }
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+class LLTwitterShareResponder : public LLHTTPClient::Responder
+{
+	LOG_CLASS(LLTwitterShareResponder);
+public:
+    
+	LLTwitterShareResponder()
+	{
+		LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_POSTING);
+	}
+	
+	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	{
+		if (isGoodStatus(status))
+		{
+            toast_user_for_twitter_success();
+			LL_DEBUGS("TwitterConnect") << "Post successful. content: " << content << LL_ENDL;
+			
+			LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_POSTED);
+		}
+		else if (status == 404)
+		{
+			LLTwitterConnect::instance().connectToTwitter();
+		}
+		else
+		{
+            LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_POST_FAILED);
+            log_twitter_connect_error("Share", status, reason, content.get("error_code"), content.get("error_description"));
+		}
+	}
+    
+    void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+    {
+        if (status == 302)
+        {
+            LLTwitterConnect::instance().openTwitterWeb(content["location"]);
+        }
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+class LLTwitterDisconnectResponder : public LLHTTPClient::Responder
+{
+	LOG_CLASS(LLTwitterDisconnectResponder);
+public:
+ 
+	LLTwitterDisconnectResponder()
+	{
+		LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_DISCONNECTING);
+	}
+
+	void setUserDisconnected()
+	{
+		// Clear data
+		LLTwitterConnect::instance().clearInfo();
+
+		//Notify state change
+		LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_NOT_CONNECTED);
+	}
+
+	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	{
+		if (isGoodStatus(status)) 
+		{
+			LL_DEBUGS("TwitterConnect") << "Disconnect successful. content: " << content << LL_ENDL;
+			setUserDisconnected();
+
+		}
+		//User not found so already disconnected
+		else if(status == 404)
+		{
+			LL_DEBUGS("TwitterConnect") << "Already disconnected. content: " << content << LL_ENDL;
+			setUserDisconnected();
+		}
+		else
+		{
+			LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_DISCONNECT_FAILED);
+            log_twitter_connect_error("Disconnect", status, reason, content.get("error_code"), content.get("error_description"));
+		}
+	}
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+class LLTwitterConnectedResponder : public LLHTTPClient::Responder
+{
+	LOG_CLASS(LLTwitterConnectedResponder);
+public:
+    
+	LLTwitterConnectedResponder(bool auto_connect) : mAutoConnect(auto_connect)
+    {
+		LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS);
+    }
+    
+	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	{
+		if (isGoodStatus(status))
+		{
+			LL_DEBUGS("TwitterConnect") << "Connect successful. content: " << content << LL_ENDL;
+            
+            LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTED);
+		}
+		else
+		{
+			// show the twitter login page if not connected yet
+			if (status == 404)
+			{
+				if (mAutoConnect)
+				{
+					LLTwitterConnect::instance().connectToTwitter();
+				}
+				else
+				{
+					LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_NOT_CONNECTED);
+				}
+			}
+            else
+            {
+                LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
+				log_twitter_connect_error("Connected", status, reason, content.get("error_code"), content.get("error_description"));
+            }
+		}
+	}
+    
+private:
+	bool mAutoConnect;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+class LLTwitterInfoResponder : public LLHTTPClient::Responder
+{
+	LOG_CLASS(LLTwitterInfoResponder);
+public:
+
+	virtual void completed(U32 status, const std::string& reason, const LLSD& info)
+	{
+		if (isGoodStatus(status))
+		{
+			llinfos << "Twitter: Info received" << llendl;
+			LL_DEBUGS("TwitterConnect") << "Getting Twitter info successful. info: " << info << LL_ENDL;
+			LLTwitterConnect::instance().storeInfo(info);
+		}
+		else
+		{
+			log_twitter_connect_error("Info", status, reason, info.get("error_code"), info.get("error_description"));
+		}
+	}
+
+	void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+	{
+		if (status == 302)
+		{
+			LLTwitterConnect::instance().openTwitterWeb(content["location"]);
+		}
+	}
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+LLTwitterConnect::LLTwitterConnect()
+:	mConnectionState(TWITTER_NOT_CONNECTED),
+	mConnected(false),
+	mInfo(),
+	mRefreshInfo(false),
+	mReadFromMaster(false)
+{
+}
+
+void LLTwitterConnect::openTwitterWeb(std::string url)
+{
+	// Open the URL in an internal browser window without navigation UI
+	LLFloaterWebContent::Params p;
+    p.url(url).show_chrome(true);
+    p.url(url).allow_address_entry(false);
+    p.url(url).allow_back_forward_navigation(false);
+    p.url(url).trusted_content(true);
+	LLFloater *floater = LLFloaterReg::showInstance("fbc_web", p);
+	//the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems).
+	//So when showing the internal web browser, set focus to it's containing floater "fbc_web". When a mouse event 
+	//occurs on the "webbrowser" panel part of the floater, a mouse cursor will properly show and the "webbrowser" will gain focus.
+	//fbc_web floater contains the "webbrowser" panel.    JIRA: ACME-744
+	gFocusMgr.setKeyboardFocus( floater );
+
+	//LLUrlAction::openURLExternal(url);
+}
+
+std::string LLTwitterConnect::getTwitterConnectURL(const std::string& route, bool include_read_from_master)
+{
+    std::string url("");
+    LLViewerRegion *regionp = gAgent.getRegion();
+    if (regionp)
+    {
+        url = regionp->getCapability("TwitterConnect");
+        url += route;
+    
+        if (include_read_from_master && mReadFromMaster)
+        {
+            url += "?read_from_master=true";
+        }
+    }
+	return url;
+}
+
+void LLTwitterConnect::connectToTwitter(const std::string& request_token, const std::string& oauth_verifier)
+{
+	LLSD body;
+	if (!request_token.empty())
+		body["request_token"] = request_token;
+	if (!oauth_verifier.empty())
+		body["oauth_verifier"] = oauth_verifier;
+    
+	LLHTTPClient::put(getTwitterConnectURL("/connection"), body, new LLTwitterConnectResponder());
+}
+
+void LLTwitterConnect::disconnectFromTwitter()
+{
+	LLHTTPClient::del(getTwitterConnectURL("/connection"), new LLTwitterDisconnectResponder());
+}
+
+void LLTwitterConnect::checkConnectionToTwitter(bool auto_connect)
+{
+	const bool follow_redirects = false;
+	const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+	LLHTTPClient::get(getTwitterConnectURL("/connection", true), new LLTwitterConnectedResponder(auto_connect),
+						LLSD(), timeout, follow_redirects);
+}
+
+void LLTwitterConnect::loadTwitterInfo()
+{
+	if(mRefreshInfo)
+	{
+		const bool follow_redirects = false;
+		const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
+		LLHTTPClient::get(getTwitterConnectURL("/info", true), new LLTwitterInfoResponder(),
+			LLSD(), timeout, follow_redirects);
+	}
+}
+
+void LLTwitterConnect::uploadPhoto(const std::string& image_url, const std::string& status)
+{
+	LLSD body;
+	body["image"] = image_url;
+	body["status"] = status;
+	
+    // Note: we can use that route for different publish action. We should be able to use the same responder.
+	LLHTTPClient::post(getTwitterConnectURL("/share/photo", true), body, new LLTwitterShareResponder());
+}
+
+void LLTwitterConnect::uploadPhoto(LLPointer<LLImageFormatted> image, const std::string& status)
+{
+	std::string imageFormat;
+	if (dynamic_cast<LLImagePNG*>(image.get()))
+	{
+		imageFormat = "png";
+	}
+	else if (dynamic_cast<LLImageJPEG*>(image.get()))
+	{
+		imageFormat = "jpg";
+	}
+	else
+	{
+		llwarns << "Image to upload is not a PNG or JPEG" << llendl;
+		return;
+	}
+	
+	// All this code is mostly copied from LLWebProfile::post()
+	const std::string boundary = "----------------------------0123abcdefab";
+
+	LLSD headers;
+	headers["Content-Type"] = "multipart/form-data; boundary=" + boundary;
+
+	std::ostringstream body;
+
+	// *NOTE: The order seems to matter.
+	body	<< "--" << boundary << "\r\n"
+			<< "Content-Disposition: form-data; name=\"status\"\r\n\r\n"
+			<< status << "\r\n";
+
+	body	<< "--" << boundary << "\r\n"
+			<< "Content-Disposition: form-data; name=\"image\"; filename=\"snapshot." << imageFormat << "\"\r\n"
+			<< "Content-Type: image/" << imageFormat << "\r\n\r\n";
+
+	// Insert the image data.
+	// *FIX: Treating this as a string will probably screw it up ...
+	U8* image_data = image->getData();
+	for (S32 i = 0; i < image->getDataSize(); ++i)
+	{
+		body << image_data[i];
+	}
+
+	body <<	"\r\n--" << boundary << "--\r\n";
+
+	// postRaw() takes ownership of the buffer and releases it later.
+	size_t size = body.str().size();
+	U8 *data = new U8[size];
+	memcpy(data, body.str().data(), size);
+	
+    // Note: we can use that route for different publish action. We should be able to use the same responder.
+	LLHTTPClient::postRaw(getTwitterConnectURL("/share/photo", true), data, size, new LLTwitterShareResponder(), headers);
+}
+
+void LLTwitterConnect::updateStatus(const std::string& status)
+{
+	LLSD body;
+	body["status"] = status;
+	
+    // Note: we can use that route for different publish action. We should be able to use the same responder.
+	LLHTTPClient::post(getTwitterConnectURL("/share/status", true), body, new LLTwitterShareResponder());
+}
+
+void LLTwitterConnect::storeInfo(const LLSD& info)
+{
+	mInfo = info;
+	mRefreshInfo = false;
+
+	sInfoWatcher->post(info);
+}
+
+const LLSD& LLTwitterConnect::getInfo() const
+{
+	return mInfo;
+}
+
+void LLTwitterConnect::clearInfo()
+{
+	mInfo = LLSD();
+}
+
+void LLTwitterConnect::setDataDirty()
+{
+	mRefreshInfo = true;
+}
+
+void LLTwitterConnect::setConnectionState(LLTwitterConnect::EConnectionState connection_state)
+{
+	if(connection_state == TWITTER_CONNECTED)
+	{
+		mReadFromMaster = true;
+		setConnected(true);
+		setDataDirty();
+	}
+	else if(connection_state == TWITTER_NOT_CONNECTED)
+	{
+		setConnected(false);
+	}
+	else if(connection_state == TWITTER_POSTED)
+	{
+		mReadFromMaster = false;
+	}
+
+	if (mConnectionState != connection_state)
+	{
+		LLSD state_info;
+		state_info["enum"] = connection_state;
+		sStateWatcher->post(state_info);
+	}
+	
+	mConnectionState = connection_state;
+}
+
+void LLTwitterConnect::setConnected(bool connected)
+{
+	mConnected = connected;
+}
diff --git a/indra/newview/lltwitterconnect.h b/indra/newview/lltwitterconnect.h
new file mode 100644
index 0000000000..c1df13f18c
--- /dev/null
+++ b/indra/newview/lltwitterconnect.h
@@ -0,0 +1,99 @@
+/** 
+ * @file lltwitterconnect.h
+ * @author Merov, Cho
+ * @brief Connection to Twitter Service
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTWITTERCONNECT_H
+#define LL_LLTWITTERCONNECT_H
+
+#include "llsingleton.h"
+#include "llimage.h"
+
+class LLEventPump;
+
+/**
+ * @class LLTwitterConnect
+ *
+ * Manages authentication to, and interaction with, a web service allowing the
+ * the viewer to post status updates and upload photos to Twitter.
+ */
+class LLTwitterConnect : public LLSingleton<LLTwitterConnect>
+{
+	LOG_CLASS(LLTwitterConnect);
+public:
+    enum EConnectionState
+	{
+		TWITTER_NOT_CONNECTED = 0,
+		TWITTER_CONNECTION_IN_PROGRESS = 1,
+		TWITTER_CONNECTED = 2,
+		TWITTER_CONNECTION_FAILED = 3,
+		TWITTER_POSTING = 4,
+		TWITTER_POSTED = 5,
+		TWITTER_POST_FAILED = 6,
+		TWITTER_DISCONNECTING = 7,
+		TWITTER_DISCONNECT_FAILED = 8
+	};
+	
+	void connectToTwitter(const std::string& request_token = "", const std::string& oauth_verifier = "");	// Initiate the complete Twitter connection. Please use checkConnectionToTwitter() in normal use.
+	void disconnectFromTwitter();																			// Disconnect from the Twitter service.
+    void checkConnectionToTwitter(bool auto_connect = false);												// Check if an access token is available on the Twitter service. If not, call connectToTwitter().
+    
+	void loadTwitterInfo();
+	void uploadPhoto(const std::string& image_url, const std::string& status);
+	void uploadPhoto(LLPointer<LLImageFormatted> image, const std::string& status);
+	void updateStatus(const std::string& status);
+	
+	void storeInfo(const LLSD& info);
+	const LLSD& getInfo() const;
+	void clearInfo();
+	void setDataDirty();
+    
+    void setConnectionState(EConnectionState connection_state);
+	void setConnected(bool connected);
+	bool isConnected() { return mConnected; }
+	bool isTransactionOngoing() { return ((mConnectionState == TWITTER_CONNECTION_IN_PROGRESS) || (mConnectionState == TWITTER_POSTING) || (mConnectionState == TWITTER_DISCONNECTING)); }
+    EConnectionState getConnectionState() { return mConnectionState; }
+    
+    void openTwitterWeb(std::string url);
+
+private:
+	friend class LLSingleton<LLTwitterConnect>;
+
+	LLTwitterConnect();
+	~LLTwitterConnect() {};
+ 	std::string getTwitterConnectURL(const std::string& route = "", bool include_read_from_master = false);
+
+    EConnectionState mConnectionState;
+	BOOL mConnected;
+	LLSD mInfo;
+	bool mRefreshInfo;
+	bool mReadFromMaster;
+	
+	static boost::scoped_ptr<LLEventPump> sStateWatcher;
+	static boost::scoped_ptr<LLEventPump> sInfoWatcher;
+	static boost::scoped_ptr<LLEventPump> sContentWatcher;
+};
+
+#endif // LL_LLTWITTERCONNECT_H
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index b562c5cb5e..a3c0682aea 100755
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -6052,6 +6052,13 @@ Please select at least one type of content to search (General, Moderate, or Adul
     [MESSAGE]
   </notification>
 
+  <notification
+   icon="notify.tga"
+   name="TwitterConnect"
+   type="notifytip">
+    [MESSAGE]
+  </notification>
+
   <notification
    icon="notify.tga"
    name="PaymentReceived"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 0d2083632d..df04ddee86 100755
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3445,6 +3445,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
   <string name="flickr_post_success">
     You posted to Flickr.
   </string>
+  <string name="twitter_post_success">
+    You posted to Twitter.
+  </string>
 
   <string name="no_session_message">
     (IM Session Doesn't Exist)
-- 
cgit v1.2.3


From 0e71fb3c9d82bf2a307431f68f8ec84d223a4887 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Sat, 2 Nov 2013 01:50:17 +0100
Subject: added Flickr floater for ACME-1136, ACME-1137, ACME-1138, ACME-1140,
 and ACME-1141

---
 indra/newview/CMakeLists.txt                       |   2 +
 indra/newview/llfacebookconnect.cpp                |  33 +-
 indra/newview/llflickrconnect.cpp                  |  36 +-
 indra/newview/llfloaterflickr.cpp                  | 669 +++++++++++++++++++++
 indra/newview/llfloaterflickr.h                    | 122 ++++
 indra/newview/llfloatersnapshot.cpp                |   4 +-
 indra/newview/llfloaterwebcontent.cpp              |  10 +
 indra/newview/llsnapshotlivepreview.cpp            |   3 +
 indra/newview/lltwitterconnect.cpp                 |  33 -
 indra/newview/llviewerfloaterreg.cpp               |   4 +-
 .../skins/default/xui/en/floater_flickr.xml        |  89 +++
 indra/newview/skins/default/xui/en/menu_viewer.xml |  23 +-
 .../skins/default/xui/en/panel_flickr_account.xml  |  75 +++
 .../skins/default/xui/en/panel_flickr_photo.xml    | 152 +++++
 indra/newview/skins/default/xui/en/strings.xml     |  20 +-
 15 files changed, 1186 insertions(+), 89 deletions(-)
 create mode 100644 indra/newview/llfloaterflickr.cpp
 create mode 100644 indra/newview/llfloaterflickr.h
 create mode 100644 indra/newview/skins/default/xui/en/floater_flickr.xml
 create mode 100644 indra/newview/skins/default/xui/en/panel_flickr_account.xml
 create mode 100644 indra/newview/skins/default/xui/en/panel_flickr_photo.xml

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index ac2d3f8ff4..226c739e48 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -229,6 +229,7 @@ set(viewer_SOURCE_FILES
     llfloatereditwater.cpp
     llfloaterenvironmentsettings.cpp
     llfloaterevent.cpp
+    llfloaterflickr.cpp
     llfloaterfonttest.cpp
     llfloatergesture.cpp
     llfloatergodtools.cpp
@@ -819,6 +820,7 @@ set(viewer_HEADER_FILES
     llfloatereditwater.h
     llfloaterenvironmentsettings.h
     llfloaterevent.h
+    llfloaterflickr.h
     llfloaterfonttest.h
     llfloatergesture.h
     llfloatergodtools.h
diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index 2434272ef7..99fcab3dc3 100644
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -28,6 +28,8 @@
 #include "llviewerprecompiledheaders.h"
 
 #include "llfacebookconnect.h"
+#include "llflickrconnect.h"
+#include "lltwitterconnect.h"
 
 #include "llagent.h"
 #include "llcallingcard.h"			// for LLAvatarTracker
@@ -76,7 +78,7 @@ public:
 	{
 		if (tokens.size() >= 2)
 		{
-			if (tokens[0].asString() == "connect" && tokens[1].asString() == "facebook")
+			if (tokens[0].asString() == "connect")
 			{
 				// this command probably came from the fbc_web browser, so close it
 				LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web");
@@ -85,12 +87,33 @@ public:
 					fbc_web->closeFloater();
 				}
 
-				// connect to facebook
-				if (query_map.has("code"))
+				if (tokens[1].asString() == "facebook")
 				{
-                    LLFacebookConnect::instance().connectToFacebook(query_map["code"], query_map.get("state"));
+					// connect to facebook
+					if (query_map.has("code"))
+					{
+						LLFacebookConnect::instance().connectToFacebook(query_map["code"], query_map.get("state"));
+					}
+					return true;
+				}
+				else if (tokens[1].asString() == "flickr")
+				{
+					// connect to flickr
+					if (query_map.has("oauth_token"))
+					{
+						LLFlickrConnect::instance().connectToFlickr(query_map["oauth_token"], query_map.get("oauth_verifier"));
+					}
+					return true;
+				}
+				else if (tokens[1].asString() == "twitter")
+				{
+					// connect to twitter
+					if (query_map.has("oauth_token"))
+					{
+						LLTwitterConnect::instance().connectToTwitter(query_map["oauth_token"], query_map.get("oauth_verifier"));
+					}
+					return true;
 				}
-				return true;
 			}
 		}
 		return false;
diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp
index ba9be3af24..62c8110ea7 100644
--- a/indra/newview/llflickrconnect.cpp
+++ b/indra/newview/llflickrconnect.cpp
@@ -65,39 +65,6 @@ void toast_user_for_flickr_success()
     LLNotificationsUtil::add("FlickrConnect", args);
 }
 
-///////////////////////////////////////////////////////////////////////////////
-//
-class LLFlickrConnectHandler : public LLCommandHandler
-{
-public:
-	LLFlickrConnectHandler() : LLCommandHandler("fbc", UNTRUSTED_THROTTLE) { }
-    
-	bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
-	{
-		if (tokens.size() >= 2)
-		{
-			if (tokens[0].asString() == "connect" && tokens[1].asString() == "flickr")
-			{
-				// this command probably came from the fbc_web browser, so close it
-				LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web");
-				if (fbc_web)
-				{
-					fbc_web->closeFloater();
-				}
-
-				// connect to flickr
-				if (query_map.has("oauth_token"))
-				{
-                    LLFlickrConnect::instance().connectToFlickr(query_map["oauth_token"], query_map.get("oauth_verifier"));
-				}
-				return true;
-			}
-		}
-		return false;
-	}
-};
-LLFlickrConnectHandler gFlickrConnectHandler;
-
 ///////////////////////////////////////////////////////////////////////////////
 //
 class LLFlickrConnectResponder : public LLHTTPClient::Responder
@@ -329,7 +296,8 @@ std::string LLFlickrConnect::getFlickrConnectURL(const std::string& route, bool
     LLViewerRegion *regionp = gAgent.getRegion();
     if (regionp)
     {
-        url = regionp->getCapability("FlickrConnect");
+		url = "http://pdp15.lindenlab.com/flickr/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
+        //url = regionp->getCapability("FlickrConnect");
         url += route;
     
         if (include_read_from_master && mReadFromMaster)
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
new file mode 100644
index 0000000000..290d174619
--- /dev/null
+++ b/indra/newview/llfloaterflickr.cpp
@@ -0,0 +1,669 @@
+/** 
+* @file llfloaterflickr.cpp
+* @brief Implementation of llfloaterflickr
+* @author cho@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterflickr.h"
+
+#include "llagent.h"
+#include "llagentui.h"
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "llflickrconnect.h"
+#include "llfloaterreg.h"
+#include "lliconctrl.h"
+#include "llresmgr.h"		// LLLocale
+#include "llsdserialize.h"
+#include "llloadingindicator.h"
+#include "llplugincookiestore.h"
+#include "llslurl.h"
+#include "lltrans.h"
+#include "llsnapshotlivepreview.h"
+#include "llviewerregion.h"
+#include "llviewercontrol.h"
+#include "llviewermedia.h"
+
+static LLRegisterPanelClassWrapper<LLFlickrPhotoPanel> t_panel_photo("llflickrphotopanel");
+static LLRegisterPanelClassWrapper<LLFlickrAccountPanel> t_panel_account("llflickraccountpanel");
+
+const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
+const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=flickr&utm_medium=photo&utm_campaign=slshare";
+
+///////////////////////////
+//LLFlickrPhotoPanel///////
+///////////////////////////
+
+LLFlickrPhotoPanel::LLFlickrPhotoPanel() :
+mSnapshotPanel(NULL),
+mResolutionComboBox(NULL),
+mRefreshBtn(NULL),
+mWorkingLabel(NULL),
+mThumbnailPlaceholder(NULL),
+mCaptionTextBox(NULL),
+mLocationCheckbox(NULL),
+mPostButton(NULL)
+{
+	mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFlickrPhotoPanel::onSend, this));
+	mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFlickrPhotoPanel::onClickNewSnapshot, this));
+}
+
+LLFlickrPhotoPanel::~LLFlickrPhotoPanel()
+{
+	if(mPreviewHandle.get())
+	{
+		mPreviewHandle.get()->die();
+	}
+}
+
+BOOL LLFlickrPhotoPanel::postBuild()
+{
+	setVisibleCallback(boost::bind(&LLFlickrPhotoPanel::onVisibilityChange, this, _2));
+	
+	mSnapshotPanel = getChild<LLUICtrl>("snapshot_panel");
+	mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
+	mResolutionComboBox->setCommitCallback(boost::bind(&LLFlickrPhotoPanel::updateResolution, this, TRUE));
+	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
+    mWorkingLabel = getChild<LLUICtrl>("working_lbl");
+	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
+	mCaptionTextBox = getChild<LLUICtrl>("photo_caption");
+	mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
+	mPostButton = getChild<LLUICtrl>("post_photo_btn");
+	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
+
+	return LLPanel::postBuild();
+}
+
+void LLFlickrPhotoPanel::draw()
+{ 
+	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
+
+    // Enable interaction only if no transaction with the service is on-going (prevent duplicated posts)
+    bool no_ongoing_connection = !(LLFlickrConnect::instance().isTransactionOngoing());
+    mCancelButton->setEnabled(no_ongoing_connection);
+    mCaptionTextBox->setEnabled(no_ongoing_connection);
+    mResolutionComboBox->setEnabled(no_ongoing_connection);
+    mRefreshBtn->setEnabled(no_ongoing_connection);
+    mLocationCheckbox->setEnabled(no_ongoing_connection);
+    
+    // Display the preview if one is available
+	if (previewp && previewp->getThumbnailImage())
+	{
+		const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect();
+		const S32 thumbnail_w = previewp->getThumbnailWidth();
+		const S32 thumbnail_h = previewp->getThumbnailHeight();
+
+		// calc preview offset within the preview rect
+		const S32 local_offset_x = (thumbnail_rect.getWidth()  - thumbnail_w) / 2 ;
+		const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ;
+
+		// calc preview offset within the floater rect
+        // Hack : To get the full offset, we need to take into account each and every offset of each widgets up to the floater.
+        // This is almost as arbitrary as using a fixed offset so that's what we do here for the sake of simplicity.
+        // *TODO : Get the offset looking through the hierarchy of widgets, should be done in postBuild() so to avoid traversing the hierarchy each time.
+		S32 offset_x = thumbnail_rect.mLeft + local_offset_x - 1;
+		S32 offset_y = thumbnail_rect.mBottom + local_offset_y - 39;
+        
+		mSnapshotPanel->localPointToOtherView(offset_x, offset_y, &offset_x, &offset_y, getParentByType<LLFloater>());
+        
+		gGL.matrixMode(LLRender::MM_MODELVIEW);
+		// Apply floater transparency to the texture unless the floater is focused.
+		F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
+		LLColor4 color = LLColor4::white;
+		gl_draw_scaled_image(offset_x, offset_y, 
+			thumbnail_w, thumbnail_h,
+			previewp->getThumbnailImage(), color % alpha);
+
+		previewp->drawPreviewRect(offset_x, offset_y) ;
+	}
+
+    // Update the visibility of the working (computing preview) label
+    mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate()));
+    
+    // Enable Post if we have a preview to send and no on going connection being processed
+    mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()));
+    
+    // Draw the rest of the panel on top of it
+	LLPanel::draw();
+}
+
+LLSnapshotLivePreview* LLFlickrPhotoPanel::getPreviewView()
+{
+	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get();
+	return previewp;
+}
+
+void LLFlickrPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
+{
+	bool visible = new_visibility.asBoolean();
+	if (visible)
+	{
+		if (mPreviewHandle.get())
+		{
+			LLSnapshotLivePreview* preview = getPreviewView();
+			if(preview)
+			{
+				lldebugs << "opened, updating snapshot" << llendl;
+				preview->updateSnapshot(TRUE);
+			}
+		}
+		else
+		{
+			LLRect full_screen_rect = getRootView()->getRect();
+			LLSnapshotLivePreview::Params p;
+			p.rect(full_screen_rect);
+			LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
+			mPreviewHandle = previewp->getHandle();	
+
+			previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
+			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
+			//previewp->setSnapshotQuality(98);
+			previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
+
+			updateControls();
+		}
+	}
+}
+
+void LLFlickrPhotoPanel::onClickNewSnapshot()
+{
+	LLSnapshotLivePreview* previewp = getPreviewView();
+	if (previewp)
+	{
+		//setStatus(Impl::STATUS_READY);
+		lldebugs << "updating snapshot" << llendl;
+		previewp->updateSnapshot(TRUE);
+	}
+}
+
+void LLFlickrPhotoPanel::onSend()
+{
+	LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrPhotoPanel"); // just in case it is already listening
+	LLEventPumps::instance().obtain("FlickrConnectState").listen("LLFlickrPhotoPanel", boost::bind(&LLFlickrPhotoPanel::onFlickrConnectStateChange, this, _1));
+	
+	// Connect to Flickr if necessary and then post
+	if (LLFlickrConnect::instance().isConnected())
+	{
+		sendPhoto();
+	}
+	else
+	{
+		LLFlickrConnect::instance().checkConnectionToFlickr(true);
+	}
+}
+
+bool LLFlickrPhotoPanel::onFlickrConnectStateChange(const LLSD& data)
+{
+	switch (data.get("enum").asInteger())
+	{
+		case LLFlickrConnect::FLICKR_CONNECTED:
+			sendPhoto();
+			break;
+
+		case LLFlickrConnect::FLICKR_POSTED:
+			LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrPhotoPanel");
+			clearAndClose();
+			break;
+	}
+
+	return false;
+}
+
+void LLFlickrPhotoPanel::sendPhoto()
+{
+	// Get the caption
+	std::string caption = mCaptionTextBox->getValue().asString();
+
+	// Add the location if required
+	bool add_location = mLocationCheckbox->getValue().asBoolean();
+	if (add_location)
+	{
+		// Get the SLURL for the location
+		LLSLURL slurl;
+		LLAgentUI::buildSLURL(slurl);
+		std::string slurl_string = slurl.getSLURLString();
+
+		// Add query parameters so Google Analytics can track incoming clicks!
+		slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS;
+
+		// Add it to the caption (pretty crude, but we don't have a better option with photos)
+		if (caption.empty())
+			caption = slurl_string;
+		else
+			caption = caption + " " + slurl_string;
+	}
+
+	// Get the image
+	LLSnapshotLivePreview* previewp = getPreviewView();
+	
+	// Post to Flickr
+	LLFlickrConnect::instance().uploadPhoto(previewp->getFormattedImage(), "", caption, "", 1);
+
+	updateControls();
+}
+
+void LLFlickrPhotoPanel::clearAndClose()
+{
+	mCaptionTextBox->setValue("");
+
+	LLFloater* floater = getParentByType<LLFloater>();
+	if (floater)
+	{
+		floater->closeFloater();
+	}
+}
+
+void LLFlickrPhotoPanel::updateControls()
+{
+	LLSnapshotLivePreview* previewp = getPreviewView();
+	BOOL got_bytes = previewp && previewp->getDataSize() > 0;
+	BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
+	LLSnapshotLivePreview::ESnapshotType shot_type = (previewp ? previewp->getSnapshotType() : LLSnapshotLivePreview::SNAPSHOT_POSTCARD);
+
+	// *TODO: Separate maximum size for Web images from postcards
+	lldebugs << "Is snapshot up-to-date? " << got_snap << llendl;
+
+	LLLocale locale(LLLocale::USER_LOCALE);
+	std::string bytes_string;
+	if (got_snap)
+	{
+		LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 );
+	}
+
+	//getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown")); <---uses localized string
+	getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : "unknown");
+	getChild<LLUICtrl>("file_size_label")->setColor(
+		shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD 
+		&& got_bytes
+		&& previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" ));
+
+	updateResolution(FALSE);
+}
+
+void LLFlickrPhotoPanel::updateResolution(BOOL do_update)
+{
+	LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox);
+
+	std::string sdstring = combobox->getSelectedValue();
+	LLSD sdres;
+	std::stringstream sstream(sdstring);
+	LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
+
+	S32 width = sdres[0];
+	S32 height = sdres[1];
+
+	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
+	if (previewp && combobox->getCurrentIndex() >= 0)
+	{
+		S32 original_width = 0 , original_height = 0 ;
+		previewp->getSize(original_width, original_height) ;
+
+		if (width == 0 || height == 0)
+		{
+			// take resolution from current window size
+			lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl;
+			previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
+		}
+		else
+		{
+			// use the resolution from the selected pre-canned drop-down choice
+			lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl;
+			previewp->setSize(width, height);
+		}
+
+		checkAspectRatio(width);
+
+		previewp->getSize(width, height);
+		
+		if(original_width != width || original_height != height)
+		{
+			previewp->setSize(width, height);
+
+			// hide old preview as the aspect ratio could be wrong
+			lldebugs << "updating thumbnail" << llendl;
+			
+			previewp->updateSnapshot(FALSE, TRUE);
+			if(do_update)
+			{
+				lldebugs << "Will update controls" << llendl;
+				updateControls();
+                LLFlickrPhotoPanel::onClickNewSnapshot();
+			}
+		}
+		
+	}
+}
+
+void LLFlickrPhotoPanel::checkAspectRatio(S32 index)
+{
+	LLSnapshotLivePreview *previewp = getPreviewView() ;
+
+	BOOL keep_aspect = FALSE;
+
+	if (0 == index) // current window size
+	{
+		keep_aspect = TRUE;
+	}
+	else // predefined resolution
+	{
+		keep_aspect = FALSE;
+	}
+
+	if (previewp)
+	{
+		previewp->mKeepAspectRatio = keep_aspect;
+	}
+}
+
+LLUICtrl* LLFlickrPhotoPanel::getRefreshBtn()
+{
+	return mRefreshBtn;
+}
+
+///////////////////////////
+//LLFlickrAccountPanel//////
+///////////////////////////
+
+LLFlickrAccountPanel::LLFlickrAccountPanel() : 
+mAccountCaptionLabel(NULL),
+mAccountNameLabel(NULL),
+mPanelButtons(NULL),
+mConnectButton(NULL),
+mDisconnectButton(NULL)
+{
+	mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFlickrAccountPanel::onConnect, this));
+	mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFlickrAccountPanel::onDisconnect, this));
+
+	setVisibleCallback(boost::bind(&LLFlickrAccountPanel::onVisibilityChange, this, _2));
+}
+
+BOOL LLFlickrAccountPanel::postBuild()
+{
+	mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label");
+	mAccountNameLabel = getChild<LLTextBox>("account_name_label");
+	mPanelButtons = getChild<LLUICtrl>("panel_buttons");
+	mConnectButton = getChild<LLUICtrl>("connect_btn");
+	mDisconnectButton = getChild<LLUICtrl>("disconnect_btn");
+
+	return LLPanel::postBuild();
+}
+
+void LLFlickrAccountPanel::draw()
+{
+	LLFlickrConnect::EConnectionState connection_state = LLFlickrConnect::instance().getConnectionState();
+
+	//Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress
+	bool disconnecting = connection_state == LLFlickrConnect::FLICKR_DISCONNECTING;
+	mDisconnectButton->setEnabled(!disconnecting);
+
+	//Disable the 'connect' button when a connection is in progress
+	bool connecting = connection_state == LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS;
+	mConnectButton->setEnabled(!connecting);
+
+	LLPanel::draw();
+}
+
+void LLFlickrAccountPanel::onVisibilityChange(const LLSD& new_visibility)
+{
+	bool visible = new_visibility.asBoolean();
+
+	if(visible)
+	{
+		LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrAccountPanel");
+		LLEventPumps::instance().obtain("FlickrConnectState").listen("LLFlickrAccountPanel", boost::bind(&LLFlickrAccountPanel::onFlickrConnectStateChange, this, _1));
+
+		LLEventPumps::instance().obtain("FlickrConnectInfo").stopListening("LLFlickrAccountPanel");
+		LLEventPumps::instance().obtain("FlickrConnectInfo").listen("LLFlickrAccountPanel", boost::bind(&LLFlickrAccountPanel::onFlickrConnectInfoChange, this));
+
+		//Connected
+		if(LLFlickrConnect::instance().isConnected())
+		{
+			showConnectedLayout();
+		}
+		//Check if connected (show disconnected layout in meantime)
+		else
+		{
+			showDisconnectedLayout();
+		}
+        if ((LLFlickrConnect::instance().getConnectionState() == LLFlickrConnect::FLICKR_NOT_CONNECTED) ||
+            (LLFlickrConnect::instance().getConnectionState() == LLFlickrConnect::FLICKR_CONNECTION_FAILED))
+        {
+            LLFlickrConnect::instance().checkConnectionToFlickr();
+        }
+	}
+	else
+	{
+		LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrAccountPanel");
+		LLEventPumps::instance().obtain("FlickrConnectInfo").stopListening("LLFlickrAccountPanel");
+	}
+}
+
+bool LLFlickrAccountPanel::onFlickrConnectStateChange(const LLSD& data)
+{
+	if(LLFlickrConnect::instance().isConnected())
+	{
+		//In process of disconnecting so leave the layout as is
+		if(data.get("enum").asInteger() != LLFlickrConnect::FLICKR_DISCONNECTING)
+		{
+			showConnectedLayout();
+		}
+	}
+	else
+	{
+		showDisconnectedLayout();
+	}
+
+	return false;
+}
+
+bool LLFlickrAccountPanel::onFlickrConnectInfoChange()
+{
+	LLSD info = LLFlickrConnect::instance().getInfo();
+	std::string clickable_name;
+
+	//Strings of format [http://www.somewebsite.com Click Me] become clickable text
+	if(info.has("link") && info.has("name"))
+	{
+		clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]";
+	}
+
+	mAccountNameLabel->setText(clickable_name);
+
+	return false;
+}
+
+void LLFlickrAccountPanel::showConnectButton()
+{
+	if(!mConnectButton->getVisible())
+	{
+		mConnectButton->setVisible(TRUE);
+		mDisconnectButton->setVisible(FALSE);
+	}
+}
+
+void LLFlickrAccountPanel::hideConnectButton()
+{
+	if(mConnectButton->getVisible())
+	{
+		mConnectButton->setVisible(FALSE);
+		mDisconnectButton->setVisible(TRUE);
+	}
+}
+
+void LLFlickrAccountPanel::showDisconnectedLayout()
+{
+	mAccountCaptionLabel->setText(getString("flickr_disconnected"));
+	mAccountNameLabel->setText(std::string(""));
+	showConnectButton();
+}
+
+void LLFlickrAccountPanel::showConnectedLayout()
+{
+	LLFlickrConnect::instance().loadFlickrInfo();
+
+	mAccountCaptionLabel->setText(getString("flickr_connected"));
+	hideConnectButton();
+}
+
+void LLFlickrAccountPanel::onConnect()
+{
+	LLFlickrConnect::instance().checkConnectionToFlickr(true);
+
+	//Clear only the flickr browser cookies so that the flickr login screen appears
+	LLViewerMedia::getCookieStore()->removeCookiesByDomain(".flickr.com"); 
+}
+
+void LLFlickrAccountPanel::onDisconnect()
+{
+	LLFlickrConnect::instance().disconnectFromFlickr();
+
+	LLViewerMedia::getCookieStore()->removeCookiesByDomain(".flickr.com"); 
+}
+
+////////////////////////
+//LLFloaterFlickr///////
+////////////////////////
+
+LLFloaterFlickr::LLFloaterFlickr(const LLSD& key) : LLFloater(key),
+    mSocialPhotoPanel(NULL),
+    mStatusErrorText(NULL),
+    mStatusLoadingText(NULL),
+    mStatusLoadingIndicator(NULL)
+{
+	mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterFlickr::onCancel, this));
+}
+
+void LLFloaterFlickr::onCancel()
+{
+    closeFloater();
+}
+
+BOOL LLFloaterFlickr::postBuild()
+{
+    // Keep tab of the Photo Panel
+	mSocialPhotoPanel = static_cast<LLFlickrPhotoPanel*>(getChild<LLUICtrl>("panel_flickr_photo"));
+    // Connection status widgets
+    mStatusErrorText = getChild<LLTextBox>("connection_error_text");
+    mStatusLoadingText = getChild<LLTextBox>("connection_loading_text");
+    mStatusLoadingIndicator = getChild<LLUICtrl>("connection_loading_indicator");
+	return LLFloater::postBuild();
+}
+
+// static
+void LLFloaterFlickr::preUpdate()
+{
+	LLFloaterFlickr* instance = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr");
+	if (instance)
+	{
+		//Will set file size text to 'unknown'
+		instance->mSocialPhotoPanel->updateControls();
+	}
+}
+
+// static
+void LLFloaterFlickr::postUpdate()
+{
+	LLFloaterFlickr* instance = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr");
+	if (instance)
+	{
+		//Will set the file size text
+		instance->mSocialPhotoPanel->updateControls();
+
+		// The refresh button is initially hidden. We show it after the first update,
+		// i.e. after snapshot is taken
+		LLUICtrl * refresh_button = instance->mSocialPhotoPanel->getRefreshBtn();
+
+		if (!refresh_button->getVisible())
+		{
+			refresh_button->setVisible(true);
+		}
+		
+	}
+}
+
+void LLFloaterFlickr::draw()
+{
+    if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator)
+    {
+        mStatusErrorText->setVisible(false);
+        mStatusLoadingText->setVisible(false);
+        mStatusLoadingIndicator->setVisible(false);
+        LLFlickrConnect::EConnectionState connection_state = LLFlickrConnect::instance().getConnectionState();
+        std::string status_text;
+        
+        switch (connection_state)
+        {
+        case LLFlickrConnect::FLICKR_NOT_CONNECTED:
+            // No status displayed when first opening the panel and no connection done
+        case LLFlickrConnect::FLICKR_CONNECTED:
+            // When successfully connected, no message is displayed
+        case LLFlickrConnect::FLICKR_POSTED:
+            // No success message to show since we actually close the floater after successful posting completion
+            break;
+        case LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS:
+            // Connection loading indicator
+            mStatusLoadingText->setVisible(true);
+            status_text = LLTrans::getString("SocialFlickrConnecting");
+            mStatusLoadingText->setValue(status_text);
+            mStatusLoadingIndicator->setVisible(true);
+            break;
+        case LLFlickrConnect::FLICKR_POSTING:
+            // Posting indicator
+            mStatusLoadingText->setVisible(true);
+            status_text = LLTrans::getString("SocialFlickrPosting");
+            mStatusLoadingText->setValue(status_text);
+            mStatusLoadingIndicator->setVisible(true);
+			break;
+        case LLFlickrConnect::FLICKR_CONNECTION_FAILED:
+            // Error connecting to the service
+            mStatusErrorText->setVisible(true);
+            status_text = LLTrans::getString("SocialFlickrErrorConnecting");
+            mStatusErrorText->setValue(status_text);
+            break;
+        case LLFlickrConnect::FLICKR_POST_FAILED:
+            // Error posting to the service
+            mStatusErrorText->setVisible(true);
+            status_text = LLTrans::getString("SocialFlickrErrorPosting");
+            mStatusErrorText->setValue(status_text);
+            break;
+		case LLFlickrConnect::FLICKR_DISCONNECTING:
+			// Disconnecting loading indicator
+			mStatusLoadingText->setVisible(true);
+			status_text = LLTrans::getString("SocialFlickrDisconnecting");
+			mStatusLoadingText->setValue(status_text);
+			mStatusLoadingIndicator->setVisible(true);
+			break;
+		case LLFlickrConnect::FLICKR_DISCONNECT_FAILED:
+			// Error disconnecting from the service
+			mStatusErrorText->setVisible(true);
+			status_text = LLTrans::getString("SocialFlickrErrorDisconnecting");
+			mStatusErrorText->setValue(status_text);
+			break;
+        }
+    }
+	LLFloater::draw();
+}
+
diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h
new file mode 100644
index 0000000000..d98a470d5c
--- /dev/null
+++ b/indra/newview/llfloaterflickr.h
@@ -0,0 +1,122 @@
+/** 
+* @file   llfloaterflickr.h
+* @brief  Header file for llfloaterflickr
+* @author cho@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+#ifndef LL_LLFLOATERFLICKR_H
+#define LL_LLFLOATERFLICKR_H
+
+#include "llfloater.h"
+#include "lltextbox.h"
+#include "llviewertexture.h"
+
+class LLIconCtrl;
+class LLCheckBoxCtrl;
+class LLSnapshotLivePreview;
+
+class LLFlickrPhotoPanel : public LLPanel
+{
+public:
+	LLFlickrPhotoPanel();
+	~LLFlickrPhotoPanel();
+
+	BOOL postBuild();
+	void draw();
+
+	LLSnapshotLivePreview* getPreviewView();
+	void onVisibilityChange(const LLSD& new_visibility);
+	void onClickNewSnapshot();
+	void onSend();
+	bool onFlickrConnectStateChange(const LLSD& data);
+
+	void sendPhoto();
+	void clearAndClose();
+
+	void updateControls();
+	void updateResolution(BOOL do_update);
+	void checkAspectRatio(S32 index);
+	LLUICtrl* getRefreshBtn();
+
+private:
+	LLHandle<LLView> mPreviewHandle;
+
+	LLUICtrl * mSnapshotPanel;
+	LLUICtrl * mResolutionComboBox;
+	LLUICtrl * mRefreshBtn;
+	LLUICtrl * mWorkingLabel;
+	LLUICtrl * mThumbnailPlaceholder;
+	LLUICtrl * mCaptionTextBox;
+	LLUICtrl * mLocationCheckbox;
+	LLUICtrl * mPostButton;
+	LLUICtrl* mCancelButton;
+};
+
+class LLFlickrAccountPanel : public LLPanel
+{
+public:
+	LLFlickrAccountPanel();
+	BOOL postBuild();
+	void draw();
+
+private:
+	void onVisibilityChange(const LLSD& new_visibility);
+	bool onFlickrConnectStateChange(const LLSD& data);
+	bool onFlickrConnectInfoChange();
+	void onConnect();
+	void onUseAnotherAccount();
+	void onDisconnect();
+
+	void showConnectButton();
+	void hideConnectButton();
+	void showDisconnectedLayout();
+	void showConnectedLayout();
+
+	LLTextBox * mAccountCaptionLabel;
+	LLTextBox * mAccountNameLabel;
+	LLUICtrl * mPanelButtons;
+	LLUICtrl * mConnectButton;
+	LLUICtrl * mDisconnectButton;
+};
+
+
+class LLFloaterFlickr : public LLFloater
+{
+public:
+	LLFloaterFlickr(const LLSD& key);
+	BOOL postBuild();
+	void draw();
+	void onCancel();
+
+	static void preUpdate();
+	static void postUpdate();
+
+private:
+	LLFlickrPhotoPanel* mSocialPhotoPanel;
+    LLTextBox* mStatusErrorText;
+    LLTextBox* mStatusLoadingText;
+    LLUICtrl*  mStatusLoadingIndicator;
+};
+
+#endif // LL_LLFLOATERFLICKR_H
+
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index ea385d7baf..fa92ed094b 100755
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -32,6 +32,7 @@
 #include "llfacebookconnect.h"
 #include "llfloaterreg.h"
 #include "llfloatersocial.h"
+#include "llfloaterflickr.h"
 #include "llcheckboxctrl.h"
 #include "llcombobox.h"
 #include "llpostcard.h"
@@ -1265,8 +1266,9 @@ void LLFloaterSnapshot::update()
 {
 	LLFloaterSnapshot* inst = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot");
 	LLFloaterSocial* floater_social  = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social"); 
+	LLFloaterFlickr* floater_flickr  = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr"); 
 
-	if (!inst && !floater_social)
+	if (!inst && !floater_social && !floater_flickr)
 		return;
 	
 	BOOL changed = FALSE;
diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp
index 5c569b9bf0..4fa2d4cb20 100755
--- a/indra/newview/llfloaterwebcontent.cpp
+++ b/indra/newview/llfloaterwebcontent.cpp
@@ -30,6 +30,8 @@
 #include "lliconctrl.h"
 #include "llfloaterreg.h"
 #include "llfacebookconnect.h"
+#include "llflickrconnect.h"
+#include "lltwitterconnect.h"
 #include "lllayoutstack.h"
 #include "llpluginclassmedia.h"
 #include "llprogressbar.h"
@@ -297,6 +299,14 @@ void LLFloaterWebContent::onClose(bool app_quitting)
         {
             LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_FAILED);
         }
+        if (!LLFlickrConnect::instance().isConnected())
+        {
+            LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
+        }
+        if (!LLTwitterConnect::instance().isConnected())
+        {
+            LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
+        }
     }
     
 	LLViewerMedia::proxyWindowClosed(mUUID);
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 7532ebfc57..afd9942e77 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -35,6 +35,7 @@
 #include "llfloaterperms.h"
 #include "llfloaterreg.h"
 #include "llfloatersocial.h"
+#include "llfloaterflickr.h"
 #include "llimagebmp.h"
 #include "llimagej2c.h"
 #include "llimagejpeg.h"
@@ -209,6 +210,7 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail
 		mSnapshotDelayTimer.setTimerExpirySec(delay);
 		LLFloaterSnapshot::preUpdate();
 		LLFloaterSocial::preUpdate();
+		LLFloaterFlickr::preUpdate();
 	}
 
 	// Update thumbnail if requested.
@@ -766,6 +768,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 	lldebugs << "done creating snapshot" << llendl;
 	LLFloaterSnapshot::postUpdate();
 	LLFloaterSocial::postUpdate();
+	LLFloaterFlickr::postUpdate();
 
 	return TRUE;
 }
diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp
index 6efcce8127..80142e7073 100644
--- a/indra/newview/lltwitterconnect.cpp
+++ b/indra/newview/lltwitterconnect.cpp
@@ -65,39 +65,6 @@ void toast_user_for_twitter_success()
     LLNotificationsUtil::add("TwitterConnect", args);
 }
 
-///////////////////////////////////////////////////////////////////////////////
-//
-class LLTwitterConnectHandler : public LLCommandHandler
-{
-public:
-	LLTwitterConnectHandler() : LLCommandHandler("fbc", UNTRUSTED_THROTTLE) { }
-    
-	bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
-	{
-		if (tokens.size() >= 2)
-		{
-			if (tokens[0].asString() == "connect" && tokens[1].asString() == "twitter")
-			{
-				// this command probably came from the fbc_web browser, so close it
-				LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web");
-				if (fbc_web)
-				{
-					fbc_web->closeFloater();
-				}
-
-				// connect to twitter
-				if (query_map.has("oauth_token"))
-				{
-                    LLTwitterConnect::instance().connectToTwitter(query_map["oauth_token"], query_map.get("oauth_verifier"));
-				}
-				return true;
-			}
-		}
-		return false;
-	}
-};
-LLTwitterConnectHandler gTwitterConnectHandler;
-
 ///////////////////////////////////////////////////////////////////////////////
 //
 class LLTwitterConnectResponder : public LLHTTPClient::Responder
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 4ce049df03..0541da95fc 100755
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -53,13 +53,14 @@
 #include "llfloaterconversationlog.h"
 #include "llfloaterconversationpreview.h"
 #include "llfloaterdeleteenvpreset.h"
+#include "llfloaterdestinations.h"
 #include "llfloaterdisplayname.h"
 #include "llfloatereditdaycycle.h"
 #include "llfloatereditsky.h"
 #include "llfloatereditwater.h"
 #include "llfloaterenvironmentsettings.h"
 #include "llfloaterevent.h"
-#include "llfloaterdestinations.h"
+#include "llfloaterflickr.h"
 #include "llfloaterfonttest.h"
 #include "llfloatergesture.h"
 #include "llfloatergodtools.h"
@@ -305,6 +306,7 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterReg::add("settings_debug", "floater_settings_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSettingsDebug>);
 	LLFloaterReg::add("sound_devices", "floater_sound_devices.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundDevices>);
 	LLFloaterReg::add("social", "floater_social.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSocial>);
+	LLFloaterReg::add("flickr", "floater_flickr.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFlickr>);
 	LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>);
 	LLFloaterReg::add("start_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRunQueue>);
 	LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>);
diff --git a/indra/newview/skins/default/xui/en/floater_flickr.xml b/indra/newview/skins/default/xui/en/floater_flickr.xml
new file mode 100644
index 0000000000..441e3ee73d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_flickr.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<floater
+  positioning="cascading"
+  can_close="true"
+  can_resize="false"
+  help_topic="floater_flickr"
+  layout="topleft"
+  name="floater_flickr"
+  save_rect="true"
+  single_instance="true"
+  reuse_instance="true"
+  title="UPLOAD TO FLICKR"
+  height="482"
+  width="304">
+  <panel
+   height="482"
+   width="304"
+   visible="true"
+   name="background"
+   follows="all"
+   top="0"
+   left="0">
+   <tab_container
+     name="tabs"
+     tab_group="1"
+     tab_min_width="70"
+     tab_height="30"
+     tab_position="top"
+     top="7"
+     height="437"
+     halign="center">
+     <panel
+       filename="panel_flickr_photo.xml"
+       class="llflickrphotopanel"
+       follows="all"
+       label="PHOTO"
+       name="panel_flickr_photo"/>
+     <panel
+       filename="panel_flickr_account.xml"
+       class="llflickraccountpanel"
+       follows="all"
+       label="ACCOUNT"
+       name="panel_flickr_account"/>     
+    </tab_container>
+    <panel
+     name="connection_status_panel"
+     follows="left|bottom|right"
+     height="24">
+     <text
+      name="connection_error_text"
+      type="string"
+      follows="left|bottom|right"
+      top="5"
+      left="9"
+      width="250"
+      height="20"
+      wrap="true"
+      halign="left"
+      valign="center"
+      text_color="DrYellow"
+      font="SansSerif">
+      Error
+     </text>
+     <loading_indicator
+      follows="left|bottom|right"
+      height="24"
+      width="24"
+      name="connection_loading_indicator"
+      top="2"
+      left="9"
+      visible="true"/>
+     <text
+      name="connection_loading_text"
+      type="string"
+      follows="left|bottom|right"
+      top="5"
+      left_pad="5"
+      width="250"
+      height="20"
+      wrap="true"
+      halign="left"
+      valign="center"
+      text_color="EmphasisColor"
+      font="SansSerif">
+      Loading...
+    </text>
+  </panel>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index d635b8ee93..19fe706885 100755
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -15,14 +15,6 @@
          function="ShowAgentProfile"
          parameter="agent" />
       </menu_item_call>
-      <menu_item_call
-        label="Post to Facebook..."
-        name="PostToFacebook">
-        <menu_item_call.on_click
-          function="Floater.Toggle"
-          parameter="social"/>
-      </menu_item_call>      
-      <menu_item_separator/>
       <menu_item_call
        label="Appearance..."
        name="ChangeOutfit">
@@ -288,6 +280,21 @@
              parameter="conversation" />
         </menu_item_check>
         <menu_item_separator/>
+      <menu_item_call
+        label="Post to Facebook..."
+        name="PostToFacebook">
+        <menu_item_call.on_click
+          function="Floater.Toggle"
+          parameter="social"/>
+      </menu_item_call>
+      <menu_item_call
+        label="Upload to Flickr..."
+        name="UploadToFacebook">
+        <menu_item_call.on_click
+          function="Floater.Toggle"
+          parameter="flickr"/>
+      </menu_item_call>
+        <menu_item_separator/>
         <menu
          label="Voice morphing"
          name="VoiceMorphing"
diff --git a/indra/newview/skins/default/xui/en/panel_flickr_account.xml b/indra/newview/skins/default/xui/en/panel_flickr_account.xml
new file mode 100644
index 0000000000..c76a42904b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_flickr_account.xml
@@ -0,0 +1,75 @@
+<panel
+	 height="400"
+	 width="304"
+	 layout="topleft"
+   name="panel_flickr_account">
+  <string
+      name="flickr_connected"
+      value="You are connected to Flickr as:" />
+  <string
+      name="flickr_disconnected"
+      value="Not connected to Flickr" />
+  <text
+   layout="topleft"
+   length="1"
+   follows="top|left"
+   font="SansSerif"
+   height="16"
+   left="9"
+   name="account_caption_label"
+   top="21"
+   type="string">
+    Not connected to Flickr.
+  </text>
+  <text
+   layout="topleft"
+   top_pad="2"
+   length="1"
+   follows="top|left"
+   font="SansSerif"
+   height="16"
+   left="9"
+   name="account_name_label"
+   parse_urls="true"
+   type="string"/>
+  <panel
+    layout="topleft"
+    name="panel_buttons"
+    height="345"
+    left="9">
+    <button
+     layout="topleft"
+     follows="left|top"
+     top_pad="9"
+     visible="true"
+     height="23"
+     label="Connect..."
+     name="connect_btn"
+     width="210">
+      <commit_callback function="SocialSharing.Connect"/>
+    </button>
+
+    <button
+     layout="topleft"
+     follows="left|top"
+     top_delta="0"
+     height="23"
+     label="Disconnect"
+     name="disconnect_btn"
+     width="210"
+     visible="false">
+      <commit_callback function="SocialSharing.Disconnect"/>
+    </button>
+    <text
+      layout="topleft"
+      length="1"
+      follows="top|left"
+      height="16"
+      left="0"
+      name="account_learn_more_label"
+      top_pad="20"
+      type="string">
+      [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share/ta-p/2149711 Learn about posting to Flickr]
+    </text>
+  </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
new file mode 100644
index 0000000000..1fc4927ac2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
@@ -0,0 +1,152 @@
+    <panel
+      height="400"
+      width="304"
+      layout="topleft"
+      name="panel_flickr_photo">
+      <layout_stack
+	   layout="topleft"
+       border_size="0"
+       height="392"
+       follows="all"
+       orientation="vertical"
+       name="stack_photo"
+       top="8">
+        <layout_panel	
+         name="snapshot_panel"
+         height="367">
+            <combo_box
+             control_name="SocialPhotoResolution"
+             follows="left|top"
+             top="6"
+             left="9"
+             name="resolution_combobox"
+             tool_tip="Image resolution"
+             height="21"
+             width="135">
+              <combo_box.item
+               label="Current Window"
+               name="CurrentWindow"
+               value="[i0,i0]" />
+              <combo_box.item
+               label="640x480"
+               name="640x480"
+               value="[i640,i480]" />
+              <combo_box.item
+               label="800x600"
+               name="800x600"
+               value="[i800,i600]" />
+              <combo_box.item
+               label="1024x768"
+               name="1024x768"
+               value="[i1024,i768]" />
+            </combo_box>
+            <text
+             follows="left|top"
+             font="SansSerifSmall"
+             height="14"
+             left="208"
+             length="1"
+             halign="right"
+             name="file_size_label"
+             top="9"
+             type="string"
+             width="50">
+              [SIZE] KB
+            </text>
+            <panel
+                height="150"
+                width="250"
+                visible="true"
+                name="thumbnail_placeholder"
+                top="33"
+                follows="left|top"
+                left="9">
+            </panel>
+            <button
+             follows="left|top"
+             height="23"
+             label="Refresh"
+             left="9"
+             top_pad="5"
+             name="new_snapshot_btn"
+             tool_tip="Click to refresh"
+             visible="true"
+             width="100" >
+             <button.commit_callback
+               function="SocialSharing.RefreshPhoto" />
+            </button>
+            <text
+                follows="left|top"
+                font="SansSerif"
+                text_color="EmphasisColor"
+                height="14"
+                top_pad="-19"
+                left_pad="-20"
+                length="1"
+                halign="center"
+                name="working_lbl"
+                translate="false"
+                type="string"
+                visible="true"
+                width="150">
+                Refreshing...
+            </text>
+            <text
+             length="1"
+             follows="top|left|right"
+             font="SansSerif"
+             height="16"
+             left="9"
+             name="caption_label"
+             top_pad="20"
+             type="string">
+              Comment (optional):
+            </text>
+            <text_editor
+             follows="left|top"
+             height="87"
+             width="250"
+             left="9"
+             length="1"
+             max_length="700"
+             name="photo_caption"
+             type="string"
+             word_wrap="true">
+            </text_editor>
+            <check_box
+             follows="left|top"
+             initial_value="true"
+             label="Include location in posting"
+             name="add_location_cb"
+              left="9"
+              height="16"
+             top_pad="8"/>
+        </layout_panel>
+        <layout_panel
+          name="photo_button_panel"
+          height="25">
+          <button
+           follows="left|top"
+           top="0"
+           left="9"
+           height="23"
+           label="Post"
+           name="post_photo_btn"
+           width="100">
+            <button.commit_callback
+             function="SocialSharing.SendPhoto" />
+          </button>
+          <button
+               follows="left|top"
+               height="23"
+               label="Cancel"
+               name="cancel_photo_btn"
+               left_pad="15"
+               top_delta="0"
+               width="100">
+            <button.commit_callback
+             function="SocialSharing.Cancel" />
+          </button>          
+        </layout_panel>        
+      </layout_stack>
+    </panel>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index df04ddee86..ce09faeac0 100755
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -148,13 +148,19 @@ Please try logging in again in a minute.</string>
 	<string name="SentToInvalidRegion">You were sent to an invalid region.</string>
 	<string name="TestingDisconnect">Testing viewer disconnect</string>
 
-	<!-- Facebook Connect and, eventually, other Social Network -->
-	<string name="SocialFacebookConnecting">Connecting to Facebook...</string>
-	<string name="SocialFacebookPosting">Posting...</string>
-	<string name="SocialFacebookDisconnecting">Disconnecting from Facebook...</string>
-	<string name="SocialFacebookErrorConnecting">Problem connecting to Facebook</string>
-	<string name="SocialFacebookErrorPosting">Problem posting to Facebook</string>
-	<string name="SocialFacebookErrorDisconnecting">Problem disconnecting from Facebook</string>
+	<!-- SLShare: Facebook, Flickr, and so on... -->
+  <string name="SocialFacebookConnecting">Connecting to Facebook...</string>
+  <string name="SocialFacebookPosting">Posting...</string>
+  <string name="SocialFacebookDisconnecting">Disconnecting from Facebook...</string>
+  <string name="SocialFacebookErrorConnecting">Problem connecting to Facebook</string>
+  <string name="SocialFacebookErrorPosting">Problem posting to Facebook</string>
+  <string name="SocialFacebookErrorDisconnecting">Problem disconnecting from Facebook</string>
+  <string name="SocialFlickrConnecting">Connecting to Flickr...</string>
+  <string name="SocialFlickrPosting">Posting...</string>
+  <string name="SocialFlickrDisconnecting">Disconnecting from Flickr...</string>
+  <string name="SocialFlickrErrorConnecting">Problem connecting to Flickr</string>
+  <string name="SocialFlickrErrorPosting">Problem posting to Flickr</string>
+  <string name="SocialFlickrErrorDisconnecting">Problem disconnecting from Flickr</string>
     
 	<!-- Tooltip -->
 	<string name="TooltipPerson">Person</string><!-- Object under mouse pointer is an avatar -->
-- 
cgit v1.2.3


From 7c46eb17f24e30fe83469a297086aa93f100e5ed Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Mon, 4 Nov 2013 19:12:39 +0000
Subject: Changed SLShare menu text to match spec for ACME-1138

---
 indra/newview/skins/default/xui/en/menu_viewer.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 19fe706885..bbd6e94579 100755
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -281,14 +281,14 @@
         </menu_item_check>
         <menu_item_separator/>
       <menu_item_call
-        label="Post to Facebook..."
+        label="Facebook..."
         name="PostToFacebook">
         <menu_item_call.on_click
           function="Floater.Toggle"
           parameter="social"/>
       </menu_item_call>
       <menu_item_call
-        label="Upload to Flickr..."
+        label="Flickr..."
         name="UploadToFacebook">
         <menu_item_call.on_click
           function="Floater.Toggle"
-- 
cgit v1.2.3


From cea9ffe89ce98f04e311aa989cce5955e77a15ff Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Mon, 4 Nov 2013 23:42:21 +0000
Subject: added Twitter floater for ACME-1146, ACME-1147, ACME-1148, ACME-1149,
 and ACME-1150

---
 indra/newview/CMakeLists.txt                       |   2 +
 indra/newview/llfloatersnapshot.cpp                |   8 +-
 indra/newview/llfloatertwitter.cpp                 | 669 +++++++++++++++++++++
 indra/newview/llfloatertwitter.h                   | 122 ++++
 indra/newview/llsnapshotlivepreview.cpp            |   3 +
 indra/newview/lltwitterconnect.cpp                 |   3 +-
 indra/newview/llviewerfloaterreg.cpp               |   2 +
 .../skins/default/xui/en/floater_twitter.xml       |  89 +++
 indra/newview/skins/default/xui/en/menu_viewer.xml |  11 +-
 .../skins/default/xui/en/panel_twitter_account.xml |  75 +++
 .../skins/default/xui/en/panel_twitter_photo.xml   | 152 +++++
 indra/newview/skins/default/xui/en/strings.xml     |   8 +-
 12 files changed, 1137 insertions(+), 7 deletions(-)
 create mode 100644 indra/newview/llfloatertwitter.cpp
 create mode 100644 indra/newview/llfloatertwitter.h
 create mode 100644 indra/newview/skins/default/xui/en/floater_twitter.xml
 create mode 100644 indra/newview/skins/default/xui/en/panel_twitter_account.xml
 create mode 100644 indra/newview/skins/default/xui/en/panel_twitter_photo.xml

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 226c739e48..746991a6f0 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -288,6 +288,7 @@ set(viewer_SOURCE_FILES
     llfloatertos.cpp
     llfloatertoybox.cpp
     llfloatertranslationsettings.cpp
+    llfloatertwitter.cpp
     llfloateruipreview.cpp
     llfloaterurlentry.cpp
     llfloatervoiceeffect.cpp
@@ -879,6 +880,7 @@ set(viewer_HEADER_FILES
     llfloatertos.h
     llfloatertoybox.h
     llfloatertranslationsettings.h
+    llfloatertwitter.h
     llfloateruipreview.h
     llfloaterurlentry.h
     llfloatervoiceeffect.h
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index fa92ed094b..4701e128d3 100755
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -33,6 +33,7 @@
 #include "llfloaterreg.h"
 #include "llfloatersocial.h"
 #include "llfloaterflickr.h"
+#include "llfloatertwitter.h"
 #include "llcheckboxctrl.h"
 #include "llcombobox.h"
 #include "llpostcard.h"
@@ -1265,10 +1266,11 @@ S32 LLFloaterSnapshot::notify(const LLSD& info)
 void LLFloaterSnapshot::update()
 {
 	LLFloaterSnapshot* inst = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot");
-	LLFloaterSocial* floater_social  = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social"); 
-	LLFloaterFlickr* floater_flickr  = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr"); 
+	LLFloaterSocial* floater_social = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social"); 
+	LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr"); 
+	LLFloaterTwitter* floater_twitter = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter"); 
 
-	if (!inst && !floater_social && !floater_flickr)
+	if (!inst && !floater_social && !floater_flickr && !floater_twitter)
 		return;
 	
 	BOOL changed = FALSE;
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
new file mode 100644
index 0000000000..b45cf32945
--- /dev/null
+++ b/indra/newview/llfloatertwitter.cpp
@@ -0,0 +1,669 @@
+/** 
+* @file llfloatertwitter.cpp
+* @brief Implementation of llfloatertwitter
+* @author cho@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloatertwitter.h"
+
+#include "llagent.h"
+#include "llagentui.h"
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "lltwitterconnect.h"
+#include "llfloaterreg.h"
+#include "lliconctrl.h"
+#include "llresmgr.h"		// LLLocale
+#include "llsdserialize.h"
+#include "llloadingindicator.h"
+#include "llplugincookiestore.h"
+#include "llslurl.h"
+#include "lltrans.h"
+#include "llsnapshotlivepreview.h"
+#include "llviewerregion.h"
+#include "llviewercontrol.h"
+#include "llviewermedia.h"
+
+static LLRegisterPanelClassWrapper<LLTwitterPhotoPanel> t_panel_photo("lltwitterphotopanel");
+static LLRegisterPanelClassWrapper<LLTwitterAccountPanel> t_panel_account("lltwitteraccountpanel");
+
+const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
+const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=twitter&utm_medium=photo&utm_campaign=slshare";
+
+///////////////////////////
+//LLTwitterPhotoPanel///////
+///////////////////////////
+
+LLTwitterPhotoPanel::LLTwitterPhotoPanel() :
+mSnapshotPanel(NULL),
+mResolutionComboBox(NULL),
+mRefreshBtn(NULL),
+mWorkingLabel(NULL),
+mThumbnailPlaceholder(NULL),
+mCaptionTextBox(NULL),
+mLocationCheckbox(NULL),
+mPostButton(NULL)
+{
+	mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLTwitterPhotoPanel::onSend, this));
+	mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLTwitterPhotoPanel::onClickNewSnapshot, this));
+}
+
+LLTwitterPhotoPanel::~LLTwitterPhotoPanel()
+{
+	if(mPreviewHandle.get())
+	{
+		mPreviewHandle.get()->die();
+	}
+}
+
+BOOL LLTwitterPhotoPanel::postBuild()
+{
+	setVisibleCallback(boost::bind(&LLTwitterPhotoPanel::onVisibilityChange, this, _2));
+	
+	mSnapshotPanel = getChild<LLUICtrl>("snapshot_panel");
+	mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
+	mResolutionComboBox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::updateResolution, this, TRUE));
+	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
+    mWorkingLabel = getChild<LLUICtrl>("working_lbl");
+	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
+	mCaptionTextBox = getChild<LLUICtrl>("photo_caption");
+	mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
+	mPostButton = getChild<LLUICtrl>("post_photo_btn");
+	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
+
+	return LLPanel::postBuild();
+}
+
+void LLTwitterPhotoPanel::draw()
+{ 
+	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
+
+    // Enable interaction only if no transaction with the service is on-going (prevent duplicated posts)
+    bool no_ongoing_connection = !(LLTwitterConnect::instance().isTransactionOngoing());
+    mCancelButton->setEnabled(no_ongoing_connection);
+    mCaptionTextBox->setEnabled(no_ongoing_connection);
+    mResolutionComboBox->setEnabled(no_ongoing_connection);
+    mRefreshBtn->setEnabled(no_ongoing_connection);
+    mLocationCheckbox->setEnabled(no_ongoing_connection);
+    
+    // Display the preview if one is available
+	if (previewp && previewp->getThumbnailImage())
+	{
+		const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect();
+		const S32 thumbnail_w = previewp->getThumbnailWidth();
+		const S32 thumbnail_h = previewp->getThumbnailHeight();
+
+		// calc preview offset within the preview rect
+		const S32 local_offset_x = (thumbnail_rect.getWidth()  - thumbnail_w) / 2 ;
+		const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ;
+
+		// calc preview offset within the floater rect
+        // Hack : To get the full offset, we need to take into account each and every offset of each widgets up to the floater.
+        // This is almost as arbitrary as using a fixed offset so that's what we do here for the sake of simplicity.
+        // *TODO : Get the offset looking through the hierarchy of widgets, should be done in postBuild() so to avoid traversing the hierarchy each time.
+		S32 offset_x = thumbnail_rect.mLeft + local_offset_x - 1;
+		S32 offset_y = thumbnail_rect.mBottom + local_offset_y - 39;
+        
+		mSnapshotPanel->localPointToOtherView(offset_x, offset_y, &offset_x, &offset_y, getParentByType<LLFloater>());
+        
+		gGL.matrixMode(LLRender::MM_MODELVIEW);
+		// Apply floater transparency to the texture unless the floater is focused.
+		F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
+		LLColor4 color = LLColor4::white;
+		gl_draw_scaled_image(offset_x, offset_y, 
+			thumbnail_w, thumbnail_h,
+			previewp->getThumbnailImage(), color % alpha);
+
+		previewp->drawPreviewRect(offset_x, offset_y) ;
+	}
+
+    // Update the visibility of the working (computing preview) label
+    mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate()));
+    
+    // Enable Post if we have a preview to send and no on going connection being processed
+    mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()));
+    
+    // Draw the rest of the panel on top of it
+	LLPanel::draw();
+}
+
+LLSnapshotLivePreview* LLTwitterPhotoPanel::getPreviewView()
+{
+	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get();
+	return previewp;
+}
+
+void LLTwitterPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
+{
+	bool visible = new_visibility.asBoolean();
+	if (visible)
+	{
+		if (mPreviewHandle.get())
+		{
+			LLSnapshotLivePreview* preview = getPreviewView();
+			if(preview)
+			{
+				lldebugs << "opened, updating snapshot" << llendl;
+				preview->updateSnapshot(TRUE);
+			}
+		}
+		else
+		{
+			LLRect full_screen_rect = getRootView()->getRect();
+			LLSnapshotLivePreview::Params p;
+			p.rect(full_screen_rect);
+			LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
+			mPreviewHandle = previewp->getHandle();	
+
+			previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
+			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
+			//previewp->setSnapshotQuality(98);
+			previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
+
+			updateControls();
+		}
+	}
+}
+
+void LLTwitterPhotoPanel::onClickNewSnapshot()
+{
+	LLSnapshotLivePreview* previewp = getPreviewView();
+	if (previewp)
+	{
+		//setStatus(Impl::STATUS_READY);
+		lldebugs << "updating snapshot" << llendl;
+		previewp->updateSnapshot(TRUE);
+	}
+}
+
+void LLTwitterPhotoPanel::onSend()
+{
+	LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterPhotoPanel"); // just in case it is already listening
+	LLEventPumps::instance().obtain("TwitterConnectState").listen("LLTwitterPhotoPanel", boost::bind(&LLTwitterPhotoPanel::onTwitterConnectStateChange, this, _1));
+	
+	// Connect to Twitter if necessary and then post
+	if (LLTwitterConnect::instance().isConnected())
+	{
+		sendPhoto();
+	}
+	else
+	{
+		LLTwitterConnect::instance().checkConnectionToTwitter(true);
+	}
+}
+
+bool LLTwitterPhotoPanel::onTwitterConnectStateChange(const LLSD& data)
+{
+	switch (data.get("enum").asInteger())
+	{
+		case LLTwitterConnect::TWITTER_CONNECTED:
+			sendPhoto();
+			break;
+
+		case LLTwitterConnect::TWITTER_POSTED:
+			LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterPhotoPanel");
+			clearAndClose();
+			break;
+	}
+
+	return false;
+}
+
+void LLTwitterPhotoPanel::sendPhoto()
+{
+	// Get the caption
+	std::string caption = mCaptionTextBox->getValue().asString();
+
+	// Add the location if required
+	bool add_location = mLocationCheckbox->getValue().asBoolean();
+	if (add_location)
+	{
+		// Get the SLURL for the location
+		LLSLURL slurl;
+		LLAgentUI::buildSLURL(slurl);
+		std::string slurl_string = slurl.getSLURLString();
+
+		// Add query parameters so Google Analytics can track incoming clicks!
+		slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS;
+
+		// Add it to the caption (pretty crude, but we don't have a better option with photos)
+		if (caption.empty())
+			caption = slurl_string;
+		else
+			caption = caption + " " + slurl_string;
+	}
+
+	// Get the image
+	LLSnapshotLivePreview* previewp = getPreviewView();
+	
+	// Post to Twitter
+	LLTwitterConnect::instance().uploadPhoto(previewp->getFormattedImage(), caption);
+
+	updateControls();
+}
+
+void LLTwitterPhotoPanel::clearAndClose()
+{
+	mCaptionTextBox->setValue("");
+
+	LLFloater* floater = getParentByType<LLFloater>();
+	if (floater)
+	{
+		floater->closeFloater();
+	}
+}
+
+void LLTwitterPhotoPanel::updateControls()
+{
+	LLSnapshotLivePreview* previewp = getPreviewView();
+	BOOL got_bytes = previewp && previewp->getDataSize() > 0;
+	BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
+	LLSnapshotLivePreview::ESnapshotType shot_type = (previewp ? previewp->getSnapshotType() : LLSnapshotLivePreview::SNAPSHOT_POSTCARD);
+
+	// *TODO: Separate maximum size for Web images from postcards
+	lldebugs << "Is snapshot up-to-date? " << got_snap << llendl;
+
+	LLLocale locale(LLLocale::USER_LOCALE);
+	std::string bytes_string;
+	if (got_snap)
+	{
+		LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 );
+	}
+
+	//getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown")); <---uses localized string
+	getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : "unknown");
+	getChild<LLUICtrl>("file_size_label")->setColor(
+		shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD 
+		&& got_bytes
+		&& previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" ));
+
+	updateResolution(FALSE);
+}
+
+void LLTwitterPhotoPanel::updateResolution(BOOL do_update)
+{
+	LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox);
+
+	std::string sdstring = combobox->getSelectedValue();
+	LLSD sdres;
+	std::stringstream sstream(sdstring);
+	LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
+
+	S32 width = sdres[0];
+	S32 height = sdres[1];
+
+	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
+	if (previewp && combobox->getCurrentIndex() >= 0)
+	{
+		S32 original_width = 0 , original_height = 0 ;
+		previewp->getSize(original_width, original_height) ;
+
+		if (width == 0 || height == 0)
+		{
+			// take resolution from current window size
+			lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl;
+			previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
+		}
+		else
+		{
+			// use the resolution from the selected pre-canned drop-down choice
+			lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl;
+			previewp->setSize(width, height);
+		}
+
+		checkAspectRatio(width);
+
+		previewp->getSize(width, height);
+		
+		if(original_width != width || original_height != height)
+		{
+			previewp->setSize(width, height);
+
+			// hide old preview as the aspect ratio could be wrong
+			lldebugs << "updating thumbnail" << llendl;
+			
+			previewp->updateSnapshot(FALSE, TRUE);
+			if(do_update)
+			{
+				lldebugs << "Will update controls" << llendl;
+				updateControls();
+                LLTwitterPhotoPanel::onClickNewSnapshot();
+			}
+		}
+		
+	}
+}
+
+void LLTwitterPhotoPanel::checkAspectRatio(S32 index)
+{
+	LLSnapshotLivePreview *previewp = getPreviewView() ;
+
+	BOOL keep_aspect = FALSE;
+
+	if (0 == index) // current window size
+	{
+		keep_aspect = TRUE;
+	}
+	else // predefined resolution
+	{
+		keep_aspect = FALSE;
+	}
+
+	if (previewp)
+	{
+		previewp->mKeepAspectRatio = keep_aspect;
+	}
+}
+
+LLUICtrl* LLTwitterPhotoPanel::getRefreshBtn()
+{
+	return mRefreshBtn;
+}
+
+///////////////////////////
+//LLTwitterAccountPanel//////
+///////////////////////////
+
+LLTwitterAccountPanel::LLTwitterAccountPanel() : 
+mAccountCaptionLabel(NULL),
+mAccountNameLabel(NULL),
+mPanelButtons(NULL),
+mConnectButton(NULL),
+mDisconnectButton(NULL)
+{
+	mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLTwitterAccountPanel::onConnect, this));
+	mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLTwitterAccountPanel::onDisconnect, this));
+
+	setVisibleCallback(boost::bind(&LLTwitterAccountPanel::onVisibilityChange, this, _2));
+}
+
+BOOL LLTwitterAccountPanel::postBuild()
+{
+	mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label");
+	mAccountNameLabel = getChild<LLTextBox>("account_name_label");
+	mPanelButtons = getChild<LLUICtrl>("panel_buttons");
+	mConnectButton = getChild<LLUICtrl>("connect_btn");
+	mDisconnectButton = getChild<LLUICtrl>("disconnect_btn");
+
+	return LLPanel::postBuild();
+}
+
+void LLTwitterAccountPanel::draw()
+{
+	LLTwitterConnect::EConnectionState connection_state = LLTwitterConnect::instance().getConnectionState();
+
+	//Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress
+	bool disconnecting = connection_state == LLTwitterConnect::TWITTER_DISCONNECTING;
+	mDisconnectButton->setEnabled(!disconnecting);
+
+	//Disable the 'connect' button when a connection is in progress
+	bool connecting = connection_state == LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS;
+	mConnectButton->setEnabled(!connecting);
+
+	LLPanel::draw();
+}
+
+void LLTwitterAccountPanel::onVisibilityChange(const LLSD& new_visibility)
+{
+	bool visible = new_visibility.asBoolean();
+
+	if(visible)
+	{
+		LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterAccountPanel");
+		LLEventPumps::instance().obtain("TwitterConnectState").listen("LLTwitterAccountPanel", boost::bind(&LLTwitterAccountPanel::onTwitterConnectStateChange, this, _1));
+
+		LLEventPumps::instance().obtain("TwitterConnectInfo").stopListening("LLTwitterAccountPanel");
+		LLEventPumps::instance().obtain("TwitterConnectInfo").listen("LLTwitterAccountPanel", boost::bind(&LLTwitterAccountPanel::onTwitterConnectInfoChange, this));
+
+		//Connected
+		if(LLTwitterConnect::instance().isConnected())
+		{
+			showConnectedLayout();
+		}
+		//Check if connected (show disconnected layout in meantime)
+		else
+		{
+			showDisconnectedLayout();
+		}
+        if ((LLTwitterConnect::instance().getConnectionState() == LLTwitterConnect::TWITTER_NOT_CONNECTED) ||
+            (LLTwitterConnect::instance().getConnectionState() == LLTwitterConnect::TWITTER_CONNECTION_FAILED))
+        {
+            LLTwitterConnect::instance().checkConnectionToTwitter();
+        }
+	}
+	else
+	{
+		LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterAccountPanel");
+		LLEventPumps::instance().obtain("TwitterConnectInfo").stopListening("LLTwitterAccountPanel");
+	}
+}
+
+bool LLTwitterAccountPanel::onTwitterConnectStateChange(const LLSD& data)
+{
+	if(LLTwitterConnect::instance().isConnected())
+	{
+		//In process of disconnecting so leave the layout as is
+		if(data.get("enum").asInteger() != LLTwitterConnect::TWITTER_DISCONNECTING)
+		{
+			showConnectedLayout();
+		}
+	}
+	else
+	{
+		showDisconnectedLayout();
+	}
+
+	return false;
+}
+
+bool LLTwitterAccountPanel::onTwitterConnectInfoChange()
+{
+	LLSD info = LLTwitterConnect::instance().getInfo();
+	std::string clickable_name;
+
+	//Strings of format [http://www.somewebsite.com Click Me] become clickable text
+	if(info.has("link") && info.has("name"))
+	{
+		clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]";
+	}
+
+	mAccountNameLabel->setText(clickable_name);
+
+	return false;
+}
+
+void LLTwitterAccountPanel::showConnectButton()
+{
+	if(!mConnectButton->getVisible())
+	{
+		mConnectButton->setVisible(TRUE);
+		mDisconnectButton->setVisible(FALSE);
+	}
+}
+
+void LLTwitterAccountPanel::hideConnectButton()
+{
+	if(mConnectButton->getVisible())
+	{
+		mConnectButton->setVisible(FALSE);
+		mDisconnectButton->setVisible(TRUE);
+	}
+}
+
+void LLTwitterAccountPanel::showDisconnectedLayout()
+{
+	mAccountCaptionLabel->setText(getString("twitter_disconnected"));
+	mAccountNameLabel->setText(std::string(""));
+	showConnectButton();
+}
+
+void LLTwitterAccountPanel::showConnectedLayout()
+{
+	LLTwitterConnect::instance().loadTwitterInfo();
+
+	mAccountCaptionLabel->setText(getString("twitter_connected"));
+	hideConnectButton();
+}
+
+void LLTwitterAccountPanel::onConnect()
+{
+	LLTwitterConnect::instance().checkConnectionToTwitter(true);
+
+	//Clear only the twitter browser cookies so that the twitter login screen appears
+	LLViewerMedia::getCookieStore()->removeCookiesByDomain(".twitter.com"); 
+}
+
+void LLTwitterAccountPanel::onDisconnect()
+{
+	LLTwitterConnect::instance().disconnectFromTwitter();
+
+	LLViewerMedia::getCookieStore()->removeCookiesByDomain(".twitter.com"); 
+}
+
+////////////////////////
+//LLFloaterTwitter///////
+////////////////////////
+
+LLFloaterTwitter::LLFloaterTwitter(const LLSD& key) : LLFloater(key),
+    mSocialPhotoPanel(NULL),
+    mStatusErrorText(NULL),
+    mStatusLoadingText(NULL),
+    mStatusLoadingIndicator(NULL)
+{
+	mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterTwitter::onCancel, this));
+}
+
+void LLFloaterTwitter::onCancel()
+{
+    closeFloater();
+}
+
+BOOL LLFloaterTwitter::postBuild()
+{
+    // Keep tab of the Photo Panel
+	mSocialPhotoPanel = static_cast<LLTwitterPhotoPanel*>(getChild<LLUICtrl>("panel_twitter_photo"));
+    // Connection status widgets
+    mStatusErrorText = getChild<LLTextBox>("connection_error_text");
+    mStatusLoadingText = getChild<LLTextBox>("connection_loading_text");
+    mStatusLoadingIndicator = getChild<LLUICtrl>("connection_loading_indicator");
+	return LLFloater::postBuild();
+}
+
+// static
+void LLFloaterTwitter::preUpdate()
+{
+	LLFloaterTwitter* instance = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter");
+	if (instance)
+	{
+		//Will set file size text to 'unknown'
+		instance->mSocialPhotoPanel->updateControls();
+	}
+}
+
+// static
+void LLFloaterTwitter::postUpdate()
+{
+	LLFloaterTwitter* instance = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter");
+	if (instance)
+	{
+		//Will set the file size text
+		instance->mSocialPhotoPanel->updateControls();
+
+		// The refresh button is initially hidden. We show it after the first update,
+		// i.e. after snapshot is taken
+		LLUICtrl * refresh_button = instance->mSocialPhotoPanel->getRefreshBtn();
+
+		if (!refresh_button->getVisible())
+		{
+			refresh_button->setVisible(true);
+		}
+		
+	}
+}
+
+void LLFloaterTwitter::draw()
+{
+    if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator)
+    {
+        mStatusErrorText->setVisible(false);
+        mStatusLoadingText->setVisible(false);
+        mStatusLoadingIndicator->setVisible(false);
+        LLTwitterConnect::EConnectionState connection_state = LLTwitterConnect::instance().getConnectionState();
+        std::string status_text;
+        
+        switch (connection_state)
+        {
+        case LLTwitterConnect::TWITTER_NOT_CONNECTED:
+            // No status displayed when first opening the panel and no connection done
+        case LLTwitterConnect::TWITTER_CONNECTED:
+            // When successfully connected, no message is displayed
+        case LLTwitterConnect::TWITTER_POSTED:
+            // No success message to show since we actually close the floater after successful posting completion
+            break;
+        case LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS:
+            // Connection loading indicator
+            mStatusLoadingText->setVisible(true);
+            status_text = LLTrans::getString("SocialTwitterConnecting");
+            mStatusLoadingText->setValue(status_text);
+            mStatusLoadingIndicator->setVisible(true);
+            break;
+        case LLTwitterConnect::TWITTER_POSTING:
+            // Posting indicator
+            mStatusLoadingText->setVisible(true);
+            status_text = LLTrans::getString("SocialTwitterPosting");
+            mStatusLoadingText->setValue(status_text);
+            mStatusLoadingIndicator->setVisible(true);
+			break;
+        case LLTwitterConnect::TWITTER_CONNECTION_FAILED:
+            // Error connecting to the service
+            mStatusErrorText->setVisible(true);
+            status_text = LLTrans::getString("SocialTwitterErrorConnecting");
+            mStatusErrorText->setValue(status_text);
+            break;
+        case LLTwitterConnect::TWITTER_POST_FAILED:
+            // Error posting to the service
+            mStatusErrorText->setVisible(true);
+            status_text = LLTrans::getString("SocialTwitterErrorPosting");
+            mStatusErrorText->setValue(status_text);
+            break;
+		case LLTwitterConnect::TWITTER_DISCONNECTING:
+			// Disconnecting loading indicator
+			mStatusLoadingText->setVisible(true);
+			status_text = LLTrans::getString("SocialTwitterDisconnecting");
+			mStatusLoadingText->setValue(status_text);
+			mStatusLoadingIndicator->setVisible(true);
+			break;
+		case LLTwitterConnect::TWITTER_DISCONNECT_FAILED:
+			// Error disconnecting from the service
+			mStatusErrorText->setVisible(true);
+			status_text = LLTrans::getString("SocialTwitterErrorDisconnecting");
+			mStatusErrorText->setValue(status_text);
+			break;
+        }
+    }
+	LLFloater::draw();
+}
+
diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h
new file mode 100644
index 0000000000..d0c7b57eef
--- /dev/null
+++ b/indra/newview/llfloatertwitter.h
@@ -0,0 +1,122 @@
+/** 
+* @file   llfloatertwitter.h
+* @brief  Header file for llfloatertwitter
+* @author cho@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+#ifndef LL_LLFLOATERTWITTER_H
+#define LL_LLFLOATERTWITTER_H
+
+#include "llfloater.h"
+#include "lltextbox.h"
+#include "llviewertexture.h"
+
+class LLIconCtrl;
+class LLCheckBoxCtrl;
+class LLSnapshotLivePreview;
+
+class LLTwitterPhotoPanel : public LLPanel
+{
+public:
+	LLTwitterPhotoPanel();
+	~LLTwitterPhotoPanel();
+
+	BOOL postBuild();
+	void draw();
+
+	LLSnapshotLivePreview* getPreviewView();
+	void onVisibilityChange(const LLSD& new_visibility);
+	void onClickNewSnapshot();
+	void onSend();
+	bool onTwitterConnectStateChange(const LLSD& data);
+
+	void sendPhoto();
+	void clearAndClose();
+
+	void updateControls();
+	void updateResolution(BOOL do_update);
+	void checkAspectRatio(S32 index);
+	LLUICtrl* getRefreshBtn();
+
+private:
+	LLHandle<LLView> mPreviewHandle;
+
+	LLUICtrl * mSnapshotPanel;
+	LLUICtrl * mResolutionComboBox;
+	LLUICtrl * mRefreshBtn;
+	LLUICtrl * mWorkingLabel;
+	LLUICtrl * mThumbnailPlaceholder;
+	LLUICtrl * mCaptionTextBox;
+	LLUICtrl * mLocationCheckbox;
+	LLUICtrl * mPostButton;
+	LLUICtrl* mCancelButton;
+};
+
+class LLTwitterAccountPanel : public LLPanel
+{
+public:
+	LLTwitterAccountPanel();
+	BOOL postBuild();
+	void draw();
+
+private:
+	void onVisibilityChange(const LLSD& new_visibility);
+	bool onTwitterConnectStateChange(const LLSD& data);
+	bool onTwitterConnectInfoChange();
+	void onConnect();
+	void onUseAnotherAccount();
+	void onDisconnect();
+
+	void showConnectButton();
+	void hideConnectButton();
+	void showDisconnectedLayout();
+	void showConnectedLayout();
+
+	LLTextBox * mAccountCaptionLabel;
+	LLTextBox * mAccountNameLabel;
+	LLUICtrl * mPanelButtons;
+	LLUICtrl * mConnectButton;
+	LLUICtrl * mDisconnectButton;
+};
+
+
+class LLFloaterTwitter : public LLFloater
+{
+public:
+	LLFloaterTwitter(const LLSD& key);
+	BOOL postBuild();
+	void draw();
+	void onCancel();
+
+	static void preUpdate();
+	static void postUpdate();
+
+private:
+	LLTwitterPhotoPanel* mSocialPhotoPanel;
+    LLTextBox* mStatusErrorText;
+    LLTextBox* mStatusLoadingText;
+    LLUICtrl*  mStatusLoadingIndicator;
+};
+
+#endif // LL_LLFLOATERTWITTER_H
+
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index afd9942e77..67952f83c7 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -36,6 +36,7 @@
 #include "llfloaterreg.h"
 #include "llfloatersocial.h"
 #include "llfloaterflickr.h"
+#include "llfloatertwitter.h"
 #include "llimagebmp.h"
 #include "llimagej2c.h"
 #include "llimagejpeg.h"
@@ -211,6 +212,7 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail
 		LLFloaterSnapshot::preUpdate();
 		LLFloaterSocial::preUpdate();
 		LLFloaterFlickr::preUpdate();
+		LLFloaterTwitter::preUpdate();
 	}
 
 	// Update thumbnail if requested.
@@ -769,6 +771,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 	LLFloaterSnapshot::postUpdate();
 	LLFloaterSocial::postUpdate();
 	LLFloaterFlickr::postUpdate();
+	LLFloaterTwitter::postUpdate();
 
 	return TRUE;
 }
diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp
index 80142e7073..5abd654d0c 100644
--- a/indra/newview/lltwitterconnect.cpp
+++ b/indra/newview/lltwitterconnect.cpp
@@ -296,7 +296,8 @@ std::string LLTwitterConnect::getTwitterConnectURL(const std::string& route, boo
     LLViewerRegion *regionp = gAgent.getRegion();
     if (regionp)
     {
-        url = regionp->getCapability("TwitterConnect");
+		url = "http://pdp15.lindenlab.com/twitter/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
+        //url = regionp->getCapability("TwitterConnect");
         url += route;
     
         if (include_read_from_master && mReadFromMaster)
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 0541da95fc..e74e6fef3d 100755
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -116,6 +116,7 @@
 #include "llfloatertopobjects.h"
 #include "llfloatertoybox.h"
 #include "llfloatertranslationsettings.h"
+#include "llfloatertwitter.h"
 #include "llfloateruipreview.h"
 #include "llfloatervoiceeffect.h"
 #include "llfloatervoicevolume.h"
@@ -307,6 +308,7 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterReg::add("sound_devices", "floater_sound_devices.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundDevices>);
 	LLFloaterReg::add("social", "floater_social.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSocial>);
 	LLFloaterReg::add("flickr", "floater_flickr.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFlickr>);
+	LLFloaterReg::add("twitter", "floater_twitter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTwitter>);
 	LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>);
 	LLFloaterReg::add("start_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRunQueue>);
 	LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>);
diff --git a/indra/newview/skins/default/xui/en/floater_twitter.xml b/indra/newview/skins/default/xui/en/floater_twitter.xml
new file mode 100644
index 0000000000..7007a14cdb
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_twitter.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<floater
+  positioning="cascading"
+  can_close="true"
+  can_resize="false"
+  help_topic="floater_twitter"
+  layout="topleft"
+  name="floater_twitter"
+  save_rect="true"
+  single_instance="true"
+  reuse_instance="true"
+  title="TWITTER"
+  height="482"
+  width="304">
+  <panel
+   height="482"
+   width="304"
+   visible="true"
+   name="background"
+   follows="all"
+   top="0"
+   left="0">
+   <tab_container
+     name="tabs"
+     tab_group="1"
+     tab_min_width="70"
+     tab_height="30"
+     tab_position="top"
+     top="7"
+     height="437"
+     halign="center">
+     <panel
+       filename="panel_twitter_photo.xml"
+       class="lltwitterphotopanel"
+       follows="all"
+       label="COMPOSE"
+       name="panel_twitter_photo"/>
+     <panel
+       filename="panel_twitter_account.xml"
+       class="lltwitteraccountpanel"
+       follows="all"
+       label="ACCOUNT"
+       name="panel_twitter_account"/>     
+    </tab_container>
+    <panel
+     name="connection_status_panel"
+     follows="left|bottom|right"
+     height="24">
+     <text
+      name="connection_error_text"
+      type="string"
+      follows="left|bottom|right"
+      top="5"
+      left="9"
+      width="250"
+      height="20"
+      wrap="true"
+      halign="left"
+      valign="center"
+      text_color="DrYellow"
+      font="SansSerif">
+      Error
+     </text>
+     <loading_indicator
+      follows="left|bottom|right"
+      height="24"
+      width="24"
+      name="connection_loading_indicator"
+      top="2"
+      left="9"
+      visible="true"/>
+     <text
+      name="connection_loading_text"
+      type="string"
+      follows="left|bottom|right"
+      top="5"
+      left_pad="5"
+      width="250"
+      height="20"
+      wrap="true"
+      halign="left"
+      valign="center"
+      text_color="EmphasisColor"
+      font="SansSerif">
+      Loading...
+    </text>
+  </panel>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index bbd6e94579..79adb4e8bb 100755
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -282,14 +282,21 @@
         <menu_item_separator/>
       <menu_item_call
         label="Facebook..."
-        name="PostToFacebook">
+        name="Facebook">
         <menu_item_call.on_click
           function="Floater.Toggle"
           parameter="social"/>
       </menu_item_call>
+      <menu_item_call
+        label="Twitter..."
+        name="Twitter">
+        <menu_item_call.on_click
+          function="Floater.Toggle"
+          parameter="twitter"/>
+      </menu_item_call>
       <menu_item_call
         label="Flickr..."
-        name="UploadToFacebook">
+        name="Flickr">
         <menu_item_call.on_click
           function="Floater.Toggle"
           parameter="flickr"/>
diff --git a/indra/newview/skins/default/xui/en/panel_twitter_account.xml b/indra/newview/skins/default/xui/en/panel_twitter_account.xml
new file mode 100644
index 0000000000..4a413bd711
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_twitter_account.xml
@@ -0,0 +1,75 @@
+<panel
+	 height="400"
+	 width="304"
+	 layout="topleft"
+   name="panel_twitter_account">
+  <string
+      name="twitter_connected"
+      value="You are connected to Twitter as:" />
+  <string
+      name="twitter_disconnected"
+      value="Not connected to Twitter" />
+  <text
+   layout="topleft"
+   length="1"
+   follows="top|left"
+   font="SansSerif"
+   height="16"
+   left="9"
+   name="account_caption_label"
+   top="21"
+   type="string">
+    Not connected to Twitter.
+  </text>
+  <text
+   layout="topleft"
+   top_pad="2"
+   length="1"
+   follows="top|left"
+   font="SansSerif"
+   height="16"
+   left="9"
+   name="account_name_label"
+   parse_urls="true"
+   type="string"/>
+  <panel
+    layout="topleft"
+    name="panel_buttons"
+    height="345"
+    left="9">
+    <button
+     layout="topleft"
+     follows="left|top"
+     top_pad="9"
+     visible="true"
+     height="23"
+     label="Connect..."
+     name="connect_btn"
+     width="210">
+      <commit_callback function="SocialSharing.Connect"/>
+    </button>
+
+    <button
+     layout="topleft"
+     follows="left|top"
+     top_delta="0"
+     height="23"
+     label="Disconnect"
+     name="disconnect_btn"
+     width="210"
+     visible="false">
+      <commit_callback function="SocialSharing.Disconnect"/>
+    </button>
+    <text
+      layout="topleft"
+      length="1"
+      follows="top|left"
+      height="16"
+      left="0"
+      name="account_learn_more_label"
+      top_pad="20"
+      type="string">
+      [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share/ta-p/2149711 Learn about posting to Twitter]
+    </text>
+  </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
new file mode 100644
index 0000000000..058c65402a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
@@ -0,0 +1,152 @@
+    <panel
+      height="400"
+      width="304"
+      layout="topleft"
+      name="panel_twitter_photo">
+      <layout_stack
+	   layout="topleft"
+       border_size="0"
+       height="392"
+       follows="all"
+       orientation="vertical"
+       name="stack_photo"
+       top="8">
+        <layout_panel	
+         name="snapshot_panel"
+         height="367">
+            <combo_box
+             control_name="SocialPhotoResolution"
+             follows="left|top"
+             top="6"
+             left="9"
+             name="resolution_combobox"
+             tool_tip="Image resolution"
+             height="21"
+             width="135">
+              <combo_box.item
+               label="Current Window"
+               name="CurrentWindow"
+               value="[i0,i0]" />
+              <combo_box.item
+               label="640x480"
+               name="640x480"
+               value="[i640,i480]" />
+              <combo_box.item
+               label="800x600"
+               name="800x600"
+               value="[i800,i600]" />
+              <combo_box.item
+               label="1024x768"
+               name="1024x768"
+               value="[i1024,i768]" />
+            </combo_box>
+            <text
+             follows="left|top"
+             font="SansSerifSmall"
+             height="14"
+             left="208"
+             length="1"
+             halign="right"
+             name="file_size_label"
+             top="9"
+             type="string"
+             width="50">
+              [SIZE] KB
+            </text>
+            <panel
+                height="150"
+                width="250"
+                visible="true"
+                name="thumbnail_placeholder"
+                top="33"
+                follows="left|top"
+                left="9">
+            </panel>
+            <button
+             follows="left|top"
+             height="23"
+             label="Refresh"
+             left="9"
+             top_pad="5"
+             name="new_snapshot_btn"
+             tool_tip="Click to refresh"
+             visible="true"
+             width="100" >
+             <button.commit_callback
+               function="SocialSharing.RefreshPhoto" />
+            </button>
+            <text
+                follows="left|top"
+                font="SansSerif"
+                text_color="EmphasisColor"
+                height="14"
+                top_pad="-19"
+                left_pad="-20"
+                length="1"
+                halign="center"
+                name="working_lbl"
+                translate="false"
+                type="string"
+                visible="true"
+                width="150">
+                Refreshing...
+            </text>
+            <text
+             length="1"
+             follows="top|left|right"
+             font="SansSerif"
+             height="16"
+             left="9"
+             name="caption_label"
+             top_pad="20"
+             type="string">
+              Comment (optional):
+            </text>
+            <text_editor
+             follows="left|top"
+             height="87"
+             width="250"
+             left="9"
+             length="1"
+             max_length="700"
+             name="photo_caption"
+             type="string"
+             word_wrap="true">
+            </text_editor>
+            <check_box
+             follows="left|top"
+             initial_value="true"
+             label="Include location in posting"
+             name="add_location_cb"
+              left="9"
+              height="16"
+             top_pad="8"/>
+        </layout_panel>
+        <layout_panel
+          name="photo_button_panel"
+          height="25">
+          <button
+           follows="left|top"
+           top="0"
+           left="9"
+           height="23"
+           label="Post"
+           name="post_photo_btn"
+           width="100">
+            <button.commit_callback
+             function="SocialSharing.SendPhoto" />
+          </button>
+          <button
+               follows="left|top"
+               height="23"
+               label="Cancel"
+               name="cancel_photo_btn"
+               left_pad="15"
+               top_delta="0"
+               width="100">
+            <button.commit_callback
+             function="SocialSharing.Cancel" />
+          </button>          
+        </layout_panel>        
+      </layout_stack>
+    </panel>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index ce09faeac0..2b707ed84b 100755
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -148,7 +148,7 @@ Please try logging in again in a minute.</string>
 	<string name="SentToInvalidRegion">You were sent to an invalid region.</string>
 	<string name="TestingDisconnect">Testing viewer disconnect</string>
 
-	<!-- SLShare: Facebook, Flickr, and so on... -->
+	<!-- SLShare: Facebook, Flickr, and Twitter -->
   <string name="SocialFacebookConnecting">Connecting to Facebook...</string>
   <string name="SocialFacebookPosting">Posting...</string>
   <string name="SocialFacebookDisconnecting">Disconnecting from Facebook...</string>
@@ -161,6 +161,12 @@ Please try logging in again in a minute.</string>
   <string name="SocialFlickrErrorConnecting">Problem connecting to Flickr</string>
   <string name="SocialFlickrErrorPosting">Problem posting to Flickr</string>
   <string name="SocialFlickrErrorDisconnecting">Problem disconnecting from Flickr</string>
+  <string name="SocialTwitterConnecting">Connecting to Twitter...</string>
+  <string name="SocialTwitterPosting">Posting...</string>
+  <string name="SocialTwitterDisconnecting">Disconnecting from Twitter...</string>
+  <string name="SocialTwitterErrorConnecting">Problem connecting to Twitter</string>
+  <string name="SocialTwitterErrorPosting">Problem posting to Twitter</string>
+  <string name="SocialTwitterErrorDisconnecting">Problem disconnecting from Twitter</string>
     
 	<!-- Tooltip -->
 	<string name="TooltipPerson">Person</string><!-- Object under mouse pointer is an avatar -->
-- 
cgit v1.2.3


From 181a7d22964b7cfbdd108493560ea60064a65f86 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Wed, 6 Nov 2013 01:38:49 +0000
Subject: fixed backwards-compatibility with FBC SLURL for ACME-1154

---
 indra/newview/llfacebookconnect.cpp | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index 99fcab3dc3..b0111f63fa 100644
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -76,7 +76,7 @@ public:
     
 	bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
 	{
-		if (tokens.size() >= 2)
+		if (tokens.size() >= 1)
 		{
 			if (tokens[0].asString() == "connect")
 			{
@@ -87,16 +87,7 @@ public:
 					fbc_web->closeFloater();
 				}
 
-				if (tokens[1].asString() == "facebook")
-				{
-					// connect to facebook
-					if (query_map.has("code"))
-					{
-						LLFacebookConnect::instance().connectToFacebook(query_map["code"], query_map.get("state"));
-					}
-					return true;
-				}
-				else if (tokens[1].asString() == "flickr")
+				if (tokens.size() >= 2 && tokens[1].asString() == "flickr")
 				{
 					// connect to flickr
 					if (query_map.has("oauth_token"))
@@ -105,7 +96,7 @@ public:
 					}
 					return true;
 				}
-				else if (tokens[1].asString() == "twitter")
+				else if (tokens.size() >= 2 && tokens[1].asString() == "twitter")
 				{
 					// connect to twitter
 					if (query_map.has("oauth_token"))
@@ -114,6 +105,15 @@ public:
 					}
 					return true;
 				}
+				else //if (tokens.size() >= 2 && tokens[1].asString() == "facebook")
+				{
+					// connect to facebook
+					if (query_map.has("code"))
+					{
+						LLFacebookConnect::instance().connectToFacebook(query_map["code"], query_map.get("state"));
+					}
+					return true;
+				}
 			}
 		}
 		return false;
-- 
cgit v1.2.3


From 1a1826a4f7110dc2b7859f6ce871ab0ac957525f Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Wed, 6 Nov 2013 02:06:53 +0000
Subject: separated web floaters for Facebook, Flickr, and Twitter to fix
 ACME-1151

---
 indra/newview/llfacebookconnect.cpp   | 28 +++++++++++++++++++++-------
 indra/newview/llflickrconnect.cpp     |  6 +++---
 indra/newview/llfloaterwebcontent.cpp | 11 ++++++++++-
 indra/newview/lltwitterconnect.cpp    |  6 +++---
 indra/newview/llviewerfloaterreg.cpp  |  4 +++-
 5 files changed, 40 insertions(+), 15 deletions(-)

diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index b0111f63fa..bf517fbc9e 100644
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -80,15 +80,15 @@ public:
 		{
 			if (tokens[0].asString() == "connect")
 			{
-				// this command probably came from the fbc_web browser, so close it
-				LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web");
-				if (fbc_web)
-				{
-					fbc_web->closeFloater();
-				}
-
 				if (tokens.size() >= 2 && tokens[1].asString() == "flickr")
 				{
+					// this command probably came from the flickr_web browser, so close it
+					LLFloater* flickr_web = LLFloaterReg::getInstance("flickr_web");
+					if (flickr_web)
+					{
+						flickr_web->closeFloater();
+					}
+
 					// connect to flickr
 					if (query_map.has("oauth_token"))
 					{
@@ -98,6 +98,13 @@ public:
 				}
 				else if (tokens.size() >= 2 && tokens[1].asString() == "twitter")
 				{
+					// this command probably came from the twitter_web browser, so close it
+					LLFloater* twitter_web = LLFloaterReg::getInstance("twitter_web");
+					if (twitter_web)
+					{
+						twitter_web->closeFloater();
+					}
+
 					// connect to twitter
 					if (query_map.has("oauth_token"))
 					{
@@ -107,6 +114,13 @@ public:
 				}
 				else //if (tokens.size() >= 2 && tokens[1].asString() == "facebook")
 				{
+					// this command probably came from the fbc_web browser, so close it
+					LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web");
+					if (fbc_web)
+					{
+						fbc_web->closeFloater();
+					}
+
 					// connect to facebook
 					if (query_map.has("code"))
 					{
diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp
index 62c8110ea7..3da3ef22b2 100644
--- a/indra/newview/llflickrconnect.cpp
+++ b/indra/newview/llflickrconnect.cpp
@@ -280,11 +280,11 @@ void LLFlickrConnect::openFlickrWeb(std::string url)
     p.url(url).allow_address_entry(false);
     p.url(url).allow_back_forward_navigation(false);
     p.url(url).trusted_content(true);
-	LLFloater *floater = LLFloaterReg::showInstance("fbc_web", p);
+	LLFloater *floater = LLFloaterReg::showInstance("flickr_web", p);
 	//the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems).
-	//So when showing the internal web browser, set focus to it's containing floater "fbc_web". When a mouse event 
+	//So when showing the internal web browser, set focus to it's containing floater "flickr_web". When a mouse event 
 	//occurs on the "webbrowser" panel part of the floater, a mouse cursor will properly show and the "webbrowser" will gain focus.
-	//fbc_web floater contains the "webbrowser" panel.    JIRA: ACME-744
+	//flickr_web floater contains the "webbrowser" panel.    JIRA: ACME-744
 	gFocusMgr.setKeyboardFocus( floater );
 
 	//LLUrlAction::openURLExternal(url);
diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp
index 4fa2d4cb20..814c91ef6c 100755
--- a/indra/newview/llfloaterwebcontent.cpp
+++ b/indra/newview/llfloaterwebcontent.cpp
@@ -299,16 +299,25 @@ void LLFloaterWebContent::onClose(bool app_quitting)
         {
             LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_FAILED);
         }
+    }
+	// Same with Flickr
+	LLFloater* flickr_web = LLFloaterReg::getInstance("flickr_web");
+    if (flickr_web == this)
+    {
         if (!LLFlickrConnect::instance().isConnected())
         {
             LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
         }
+    }
+	// And Twitter
+	LLFloater* twitter_web = LLFloaterReg::getInstance("twitter_web");
+    if (twitter_web == this)
+    {
         if (!LLTwitterConnect::instance().isConnected())
         {
             LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
         }
     }
-    
 	LLViewerMedia::proxyWindowClosed(mUUID);
 	destroy();
 }
diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp
index 5abd654d0c..fe45d3e4d0 100644
--- a/indra/newview/lltwitterconnect.cpp
+++ b/indra/newview/lltwitterconnect.cpp
@@ -280,11 +280,11 @@ void LLTwitterConnect::openTwitterWeb(std::string url)
     p.url(url).allow_address_entry(false);
     p.url(url).allow_back_forward_navigation(false);
     p.url(url).trusted_content(true);
-	LLFloater *floater = LLFloaterReg::showInstance("fbc_web", p);
+	LLFloater *floater = LLFloaterReg::showInstance("twitter_web", p);
 	//the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems).
-	//So when showing the internal web browser, set focus to it's containing floater "fbc_web". When a mouse event 
+	//So when showing the internal web browser, set focus to it's containing floater "twitter_web". When a mouse event 
 	//occurs on the "webbrowser" panel part of the floater, a mouse cursor will properly show and the "webbrowser" will gain focus.
-	//fbc_web floater contains the "webbrowser" panel.    JIRA: ACME-744
+	//twitter_web floater contains the "webbrowser" panel.    JIRA: ACME-744
 	gFocusMgr.setKeyboardFocus( floater );
 
 	//LLUrlAction::openURLExternal(url);
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index e74e6fef3d..1e07aaf5ec 100755
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -316,8 +316,10 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>);
 	LLFloaterReg::add("my_profile", "floater_my_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
 	LLFloaterReg::add("profile", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
-	LLFloaterReg::add("how_to", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);	
+	LLFloaterReg::add("how_to", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
 	LLFloaterReg::add("fbc_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
+	LLFloaterReg::add("flickr_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
+	LLFloaterReg::add("twitter_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
 	
 	LLFloaterUIPreviewUtil::registerFloater();
 	LLFloaterReg::add("upload_anim_bvh", "floater_animation_bvh_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBvhPreview>, "upload");
-- 
cgit v1.2.3


From be23aaefe53cd245752d3973bf930c87f67c6253 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Thu, 7 Nov 2013 01:30:36 +0000
Subject: added title, descriptions, tags, and safety level to
 panel_flickr_photo.xml for ACME-1142

---
 indra/newview/llfloaterflickr.cpp                  | 40 ++++++---
 indra/newview/llfloaterflickr.h                    |  5 +-
 .../skins/default/xui/en/floater_flickr.xml        |  6 +-
 .../skins/default/xui/en/panel_flickr_account.xml  |  2 +-
 .../skins/default/xui/en/panel_flickr_photo.xml    | 98 ++++++++++++++++++++--
 .../skins/default/xui/en/panel_twitter_photo.xml   |  2 +-
 6 files changed, 126 insertions(+), 27 deletions(-)

diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 290d174619..1edc61fcf6 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -63,8 +63,11 @@ mResolutionComboBox(NULL),
 mRefreshBtn(NULL),
 mWorkingLabel(NULL),
 mThumbnailPlaceholder(NULL),
-mCaptionTextBox(NULL),
+mTitleTextBox(NULL),
+mDescriptionTextBox(NULL),
 mLocationCheckbox(NULL),
+mTagsTextBox(NULL),
+mRatingComboBox(NULL),
 mPostButton(NULL)
 {
 	mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFlickrPhotoPanel::onSend, this));
@@ -89,8 +92,11 @@ BOOL LLFlickrPhotoPanel::postBuild()
 	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
     mWorkingLabel = getChild<LLUICtrl>("working_lbl");
 	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
-	mCaptionTextBox = getChild<LLUICtrl>("photo_caption");
+	mTitleTextBox = getChild<LLUICtrl>("photo_title");
+	mDescriptionTextBox = getChild<LLUICtrl>("photo_description");
 	mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
+	mTagsTextBox = getChild<LLUICtrl>("photo_tags");
+	mRatingComboBox = getChild<LLUICtrl>("rating_combobox");
 	mPostButton = getChild<LLUICtrl>("post_photo_btn");
 	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
 
@@ -104,7 +110,10 @@ void LLFlickrPhotoPanel::draw()
     // Enable interaction only if no transaction with the service is on-going (prevent duplicated posts)
     bool no_ongoing_connection = !(LLFlickrConnect::instance().isTransactionOngoing());
     mCancelButton->setEnabled(no_ongoing_connection);
-    mCaptionTextBox->setEnabled(no_ongoing_connection);
+    mTitleTextBox->setEnabled(no_ongoing_connection);
+    mDescriptionTextBox->setEnabled(no_ongoing_connection);
+    mTagsTextBox->setEnabled(no_ongoing_connection);
+    mRatingComboBox->setEnabled(no_ongoing_connection);
     mResolutionComboBox->setEnabled(no_ongoing_connection);
     mRefreshBtn->setEnabled(no_ongoing_connection);
     mLocationCheckbox->setEnabled(no_ongoing_connection);
@@ -144,7 +153,7 @@ void LLFlickrPhotoPanel::draw()
     mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate()));
     
     // Enable Post if we have a preview to send and no on going connection being processed
-    mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()));
+    mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()) && (mRatingComboBox && mRatingComboBox->getValue().isDefined()));
     
     // Draw the rest of the panel on top of it
 	LLPanel::draw();
@@ -234,8 +243,10 @@ bool LLFlickrPhotoPanel::onFlickrConnectStateChange(const LLSD& data)
 
 void LLFlickrPhotoPanel::sendPhoto()
 {
-	// Get the caption
-	std::string caption = mCaptionTextBox->getValue().asString();
+	// Get the title, description, and tags
+	std::string title = mTitleTextBox->getValue().asString();
+	std::string description = mDescriptionTextBox->getValue().asString();
+	std::string tags = mTagsTextBox->getValue().asString();
 
 	// Add the location if required
 	bool add_location = mLocationCheckbox->getValue().asBoolean();
@@ -249,25 +260,30 @@ void LLFlickrPhotoPanel::sendPhoto()
 		// Add query parameters so Google Analytics can track incoming clicks!
 		slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS;
 
-		// Add it to the caption (pretty crude, but we don't have a better option with photos)
-		if (caption.empty())
-			caption = slurl_string;
+		// Add it to the description (pretty crude, but we don't have a better option with photos)
+		if (description.empty())
+			description = slurl_string;
 		else
-			caption = caption + " " + slurl_string;
+			description = description + " " + slurl_string;
 	}
 
+	// Get the content rating
+	int content_rating = mRatingComboBox->getValue().asInteger();
+
 	// Get the image
 	LLSnapshotLivePreview* previewp = getPreviewView();
 	
 	// Post to Flickr
-	LLFlickrConnect::instance().uploadPhoto(previewp->getFormattedImage(), "", caption, "", 1);
+	LLFlickrConnect::instance().uploadPhoto(previewp->getFormattedImage(), title, description, tags, content_rating);
 
 	updateControls();
 }
 
 void LLFlickrPhotoPanel::clearAndClose()
 {
-	mCaptionTextBox->setValue("");
+	mTitleTextBox->setValue("");
+	mDescriptionTextBox->setValue("");
+	mTagsTextBox->setValue("");
 
 	LLFloater* floater = getParentByType<LLFloater>();
 	if (floater)
diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h
index d98a470d5c..8cf2cd2dd6 100644
--- a/indra/newview/llfloaterflickr.h
+++ b/indra/newview/llfloaterflickr.h
@@ -66,8 +66,11 @@ private:
 	LLUICtrl * mRefreshBtn;
 	LLUICtrl * mWorkingLabel;
 	LLUICtrl * mThumbnailPlaceholder;
-	LLUICtrl * mCaptionTextBox;
+	LLUICtrl * mTitleTextBox;
+	LLUICtrl * mDescriptionTextBox;
 	LLUICtrl * mLocationCheckbox;
+	LLUICtrl * mTagsTextBox;
+	LLUICtrl * mRatingComboBox;
 	LLUICtrl * mPostButton;
 	LLUICtrl* mCancelButton;
 };
diff --git a/indra/newview/skins/default/xui/en/floater_flickr.xml b/indra/newview/skins/default/xui/en/floater_flickr.xml
index 441e3ee73d..57014f8427 100644
--- a/indra/newview/skins/default/xui/en/floater_flickr.xml
+++ b/indra/newview/skins/default/xui/en/floater_flickr.xml
@@ -10,10 +10,10 @@
   single_instance="true"
   reuse_instance="true"
   title="UPLOAD TO FLICKR"
-  height="482"
+  height="622"
   width="304">
   <panel
-   height="482"
+   height="622"
    width="304"
    visible="true"
    name="background"
@@ -27,7 +27,7 @@
      tab_height="30"
      tab_position="top"
      top="7"
-     height="437"
+     height="577"
      halign="center">
      <panel
        filename="panel_flickr_photo.xml"
diff --git a/indra/newview/skins/default/xui/en/panel_flickr_account.xml b/indra/newview/skins/default/xui/en/panel_flickr_account.xml
index c76a42904b..3a38852049 100644
--- a/indra/newview/skins/default/xui/en/panel_flickr_account.xml
+++ b/indra/newview/skins/default/xui/en/panel_flickr_account.xml
@@ -1,5 +1,5 @@
 <panel
-	 height="400"
+	 height="540"
 	 width="304"
 	 layout="topleft"
    name="panel_flickr_account">
diff --git a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
index 1fc4927ac2..d7d3fb6c1b 100644
--- a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
@@ -1,19 +1,19 @@
     <panel
-      height="400"
+      height="540"
       width="304"
       layout="topleft"
       name="panel_flickr_photo">
       <layout_stack
 	   layout="topleft"
        border_size="0"
-       height="392"
+       height="532"
        follows="all"
        orientation="vertical"
        name="stack_photo"
        top="8">
         <layout_panel	
          name="snapshot_panel"
-         height="367">
+         height="507">
             <combo_box
              control_name="SocialPhotoResolution"
              follows="left|top"
@@ -97,30 +97,110 @@
              font="SansSerif"
              height="16"
              left="9"
-             name="caption_label"
+             name="title_label"
              top_pad="20"
              type="string">
-              Comment (optional):
+              Title:
             </text>
             <text_editor
              follows="left|top"
-             height="87"
+             height="20"
+             width="250"
+             left="9"
+             length="1"
+             max_length="256"
+             name="photo_title"
+             type="string"
+             word_wrap="true">
+            </text_editor>
+            <text
+             length="1"
+             follows="top|left|right"
+             font="SansSerif"
+             height="16"
+             left="9"
+             name="description_label"
+             top_pad="10"
+             type="string">
+              Description:
+            </text>
+            <text_editor
+             follows="left|top"
+             height="50"
              width="250"
              left="9"
              length="1"
              max_length="700"
-             name="photo_caption"
+             name="photo_description"
              type="string"
              word_wrap="true">
             </text_editor>
             <check_box
              follows="left|top"
              initial_value="true"
-             label="Include location in posting"
+             label="Include SL location at end of description"
              name="add_location_cb"
               left="9"
               height="16"
              top_pad="8"/>
+            <text
+             length="1"
+             follows="top|left|right"
+             font="SansSerif"
+             height="16"
+             left="9"
+             name="tags_label"
+             top_pad="10"
+             type="string">
+              Tags:
+            </text>
+            <text
+              length="1"
+              follows="top|left"
+              font="SansSerifSmall"
+              text_color="White_50"
+              height="30"
+              name="tags_help_label"
+              left="50"
+              top_pad="-16"
+              type="string">
+Separate tags with spaces
+Use "" for multi-word tags
+            </text>
+            <text_editor
+             follows="left|top"
+             height="50"
+             width="250"
+             left="9"
+             length="1"
+             max_length="700"
+             name="photo_tags"
+             type="string"
+             word_wrap="true">
+            </text_editor>
+            <combo_box
+             control_name="FlickrPhotoRating"
+             follows="left|top"
+             top_pad="16"
+             left="9"
+             label="Choose Flickr rating (required)..."
+             name="rating_combobox"
+             tool_tip="Flickr content rating"
+             height="21"
+             width="250">
+              <combo_box.item
+               label="Safe"
+               name="SafeRating"
+               value="1" />
+              <combo_box.item
+               label="Moderate"
+               name="ModerateRating"
+               value="2" />
+              <combo_box.item
+               label="Restricted"
+               name="RestrictedRating"
+               value="3" />
+            </combo_box>
         </layout_panel>
         <layout_panel
           name="photo_button_panel"
@@ -130,7 +210,7 @@
            top="0"
            left="9"
            height="23"
-           label="Post"
+           label="Upload"
            name="post_photo_btn"
            width="100">
             <button.commit_callback
diff --git a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
index 058c65402a..540bc0f807 100644
--- a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
@@ -130,7 +130,7 @@
            top="0"
            left="9"
            height="23"
-           label="Post"
+           label="Tweet"
            name="post_photo_btn"
            width="100">
             <button.commit_callback
-- 
cgit v1.2.3


From 389ddfd5add78998aaadb171593b5b036d2dbee0 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Thu, 7 Nov 2013 19:06:39 +0000
Subject: updated panel_twitter_photo.xml to match design spec for ACME-1153

---
 indra/newview/llfloatertwitter.cpp                 | 61 ++++++++-----------
 indra/newview/llfloatertwitter.h                   |  4 +-
 .../skins/default/xui/en/panel_twitter_photo.xml   | 70 ++++++++++++----------
 3 files changed, 65 insertions(+), 70 deletions(-)

diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index b45cf32945..5a2402cdd6 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -63,8 +63,8 @@ mResolutionComboBox(NULL),
 mRefreshBtn(NULL),
 mWorkingLabel(NULL),
 mThumbnailPlaceholder(NULL),
-mCaptionTextBox(NULL),
-mLocationCheckbox(NULL),
+mStatusTextBox(NULL),
+mPhotoCheckbox(NULL),
 mPostButton(NULL)
 {
 	mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLTwitterPhotoPanel::onSend, this));
@@ -89,8 +89,8 @@ BOOL LLTwitterPhotoPanel::postBuild()
 	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
     mWorkingLabel = getChild<LLUICtrl>("working_lbl");
 	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
-	mCaptionTextBox = getChild<LLUICtrl>("photo_caption");
-	mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
+	mStatusTextBox = getChild<LLUICtrl>("photo_status");
+	mPhotoCheckbox = getChild<LLUICtrl>("add_photo_cb");
 	mPostButton = getChild<LLUICtrl>("post_photo_btn");
 	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
 
@@ -104,11 +104,11 @@ void LLTwitterPhotoPanel::draw()
     // Enable interaction only if no transaction with the service is on-going (prevent duplicated posts)
     bool no_ongoing_connection = !(LLTwitterConnect::instance().isTransactionOngoing());
     mCancelButton->setEnabled(no_ongoing_connection);
-    mCaptionTextBox->setEnabled(no_ongoing_connection);
-    mResolutionComboBox->setEnabled(no_ongoing_connection);
-    mRefreshBtn->setEnabled(no_ongoing_connection);
-    mLocationCheckbox->setEnabled(no_ongoing_connection);
-    
+    mStatusTextBox->setEnabled(no_ongoing_connection);
+    mResolutionComboBox->setEnabled(no_ongoing_connection && mPhotoCheckbox->getValue().asBoolean());
+    mRefreshBtn->setEnabled(no_ongoing_connection && mPhotoCheckbox->getValue().asBoolean());
+    mPhotoCheckbox->setEnabled(no_ongoing_connection);
+
     // Display the preview if one is available
 	if (previewp && previewp->getThumbnailImage())
 	{
@@ -131,7 +131,7 @@ void LLTwitterPhotoPanel::draw()
         
 		gGL.matrixMode(LLRender::MM_MODELVIEW);
 		// Apply floater transparency to the texture unless the floater is focused.
-		F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
+		F32 alpha = (mPhotoCheckbox->getValue().asBoolean() ? (getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency()) : 0.5f);
 		LLColor4 color = LLColor4::white;
 		gl_draw_scaled_image(offset_x, offset_y, 
 			thumbnail_w, thumbnail_h,
@@ -234,40 +234,31 @@ bool LLTwitterPhotoPanel::onTwitterConnectStateChange(const LLSD& data)
 
 void LLTwitterPhotoPanel::sendPhoto()
 {
-	// Get the caption
-	std::string caption = mCaptionTextBox->getValue().asString();
+	// Get the status text
+	std::string status = mStatusTextBox->getValue().asString();
 
-	// Add the location if required
-	bool add_location = mLocationCheckbox->getValue().asBoolean();
-	if (add_location)
+	// Add the photo if required
+	bool add_photo = mPhotoCheckbox->getValue().asBoolean();
+	if (add_photo)
 	{
-		// Get the SLURL for the location
-		LLSLURL slurl;
-		LLAgentUI::buildSLURL(slurl);
-		std::string slurl_string = slurl.getSLURLString();
-
-		// Add query parameters so Google Analytics can track incoming clicks!
-		slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS;
-
-		// Add it to the caption (pretty crude, but we don't have a better option with photos)
-		if (caption.empty())
-			caption = slurl_string;
-		else
-			caption = caption + " " + slurl_string;
-	}
-
-	// Get the image
-	LLSnapshotLivePreview* previewp = getPreviewView();
+		// Get the image
+		LLSnapshotLivePreview* previewp = getPreviewView();
 	
-	// Post to Twitter
-	LLTwitterConnect::instance().uploadPhoto(previewp->getFormattedImage(), caption);
+		// Post to Twitter
+		LLTwitterConnect::instance().uploadPhoto(previewp->getFormattedImage(), status);
+	}
+	else
+	{
+		// Just post the status to Twitter
+		LLTwitterConnect::instance().updateStatus(status);
+	}
 
 	updateControls();
 }
 
 void LLTwitterPhotoPanel::clearAndClose()
 {
-	mCaptionTextBox->setValue("");
+	mStatusTextBox->setValue("");
 
 	LLFloater* floater = getParentByType<LLFloater>();
 	if (floater)
diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h
index d0c7b57eef..090e01872a 100644
--- a/indra/newview/llfloatertwitter.h
+++ b/indra/newview/llfloatertwitter.h
@@ -66,8 +66,8 @@ private:
 	LLUICtrl * mRefreshBtn;
 	LLUICtrl * mWorkingLabel;
 	LLUICtrl * mThumbnailPlaceholder;
-	LLUICtrl * mCaptionTextBox;
-	LLUICtrl * mLocationCheckbox;
+	LLUICtrl * mStatusTextBox;
+	LLUICtrl * mPhotoCheckbox;
 	LLUICtrl * mPostButton;
 	LLUICtrl* mCancelButton;
 };
diff --git a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
index 540bc0f807..84206c608b 100644
--- a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
@@ -11,9 +11,43 @@
        orientation="vertical"
        name="stack_photo"
        top="8">
-        <layout_panel	
-         name="snapshot_panel"
-         height="367">
+        <layout_panel
+         name="text_panel"
+         height="140">
+          <text
+           length="1"
+           follows="top|left|right"
+           font="SansSerif"
+           height="16"
+           left="9"
+           name="status_label"
+           top="3"
+           type="string">
+            What's happening?
+          </text>
+          <text_editor
+           follows="left|top"
+           height="87"
+           width="250"
+           left="9"
+           length="1"
+           max_length="700"
+           name="photo_status"
+           type="string"
+           word_wrap="true">
+          </text_editor>
+          <check_box
+           follows="left|top"
+           initial_value="true"
+           label="Include a photo"
+           name="add_photo_cb"
+            left="9"
+            height="16"
+           top_pad="10"/>
+        </layout_panel>
+          <layout_panel
+           name="snapshot_panel"
+           height="227">
             <combo_box
              control_name="SocialPhotoResolution"
              follows="left|top"
@@ -91,36 +125,6 @@
                 width="150">
                 Refreshing...
             </text>
-            <text
-             length="1"
-             follows="top|left|right"
-             font="SansSerif"
-             height="16"
-             left="9"
-             name="caption_label"
-             top_pad="20"
-             type="string">
-              Comment (optional):
-            </text>
-            <text_editor
-             follows="left|top"
-             height="87"
-             width="250"
-             left="9"
-             length="1"
-             max_length="700"
-             name="photo_caption"
-             type="string"
-             word_wrap="true">
-            </text_editor>
-            <check_box
-             follows="left|top"
-             initial_value="true"
-             label="Include location in posting"
-             name="add_location_cb"
-              left="9"
-              height="16"
-             top_pad="8"/>
         </layout_panel>
         <layout_panel
           name="photo_button_panel"
-- 
cgit v1.2.3


From 15434d53ea1f1bca37b7b9d6d569b3cb61d09bbe Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Fri, 8 Nov 2013 00:33:14 +0000
Subject: added SLShare links to snapshot floater for ACME-1167

---
 indra/newview/llfloatertwitter.cpp                 |  6 ++--
 indra/newview/llpanelsnapshotoptions.cpp           | 36 ++++++++++++++++++++++
 .../skins/default/xui/en/floater_snapshot.xml      |  2 +-
 .../default/xui/en/panel_snapshot_options.xml      | 36 ++++++++++++++++++++++
 4 files changed, 77 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index 5a2402cdd6..1324bd5fd8 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -109,6 +109,8 @@ void LLTwitterPhotoPanel::draw()
     mRefreshBtn->setEnabled(no_ongoing_connection && mPhotoCheckbox->getValue().asBoolean());
     mPhotoCheckbox->setEnabled(no_ongoing_connection);
 
+	bool add_photo = mPhotoCheckbox->getValue().asBoolean();
+
     // Display the preview if one is available
 	if (previewp && previewp->getThumbnailImage())
 	{
@@ -131,7 +133,7 @@ void LLTwitterPhotoPanel::draw()
         
 		gGL.matrixMode(LLRender::MM_MODELVIEW);
 		// Apply floater transparency to the texture unless the floater is focused.
-		F32 alpha = (mPhotoCheckbox->getValue().asBoolean() ? (getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency()) : 0.5f);
+		F32 alpha = (add_photo ? (getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency()) : 0.5f);
 		LLColor4 color = LLColor4::white;
 		gl_draw_scaled_image(offset_x, offset_y, 
 			thumbnail_w, thumbnail_h,
@@ -144,7 +146,7 @@ void LLTwitterPhotoPanel::draw()
     mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate()));
     
     // Enable Post if we have a preview to send and no on going connection being processed
-    mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()));
+    mPostButton->setEnabled(no_ongoing_connection && ((add_photo && previewp && previewp->getSnapshotUpToDate()) || !mStatusTextBox->getValue().asString().empty()));
     
     // Draw the rest of the panel on top of it
 	LLPanel::draw();
diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp
index 554fabe5b3..1967c50a29 100755
--- a/indra/newview/llpanelsnapshotoptions.cpp
+++ b/indra/newview/llpanelsnapshotoptions.cpp
@@ -31,6 +31,7 @@
 #include "llsidetraypanelcontainer.h"
 
 #include "llfloatersnapshot.h" // FIXME: create a snapshot model
+#include "llfloaterreg.h"
 
 /**
  * Provides several ways to save a snapshot.
@@ -44,6 +45,7 @@ class LLPanelSnapshotOptions
 public:
 	LLPanelSnapshotOptions();
 	~LLPanelSnapshotOptions();
+	/*virtual*/ BOOL postBuild();
 	/*virtual*/ void onOpen(const LLSD& key);
 	/*virtual*/ void onEconomyDataChange() { updateUploadCost(); }
 
@@ -54,6 +56,9 @@ private:
 	void onSaveToEmail();
 	void onSaveToInventory();
 	void onSaveToComputer();
+	void onSendToFacebook();
+	void onSendToTwitter();
+	void onSendToFlickr();
 };
 
 static LLRegisterPanelClassWrapper<LLPanelSnapshotOptions> panel_class("llpanelsnapshotoptions");
@@ -73,6 +78,19 @@ LLPanelSnapshotOptions::~LLPanelSnapshotOptions()
 	LLGlobalEconomy::Singleton::getInstance()->removeObserver(this);
 }
 
+// virtual
+BOOL LLPanelSnapshotOptions::postBuild()
+{
+    LLTextBox* sendToFacebookTextBox = getChild<LLTextBox>("send_to_facebook_textbox");
+    sendToFacebookTextBox->setURLClickedCallback(boost::bind(&LLPanelSnapshotOptions::onSendToFacebook, this));
+    LLTextBox* sendToTwitterTextBox = getChild<LLTextBox>("send_to_twitter_textbox");
+    sendToTwitterTextBox->setURLClickedCallback(boost::bind(&LLPanelSnapshotOptions::onSendToTwitter, this));
+    LLTextBox* sendToFlickrTextBox = getChild<LLTextBox>("send_to_flickr_textbox");
+    sendToFlickrTextBox->setURLClickedCallback(boost::bind(&LLPanelSnapshotOptions::onSendToFlickr, this));
+
+	return LLPanel::postBuild();
+}
+
 // virtual
 void LLPanelSnapshotOptions::onOpen(const LLSD& key)
 {
@@ -118,3 +136,21 @@ void LLPanelSnapshotOptions::onSaveToComputer()
 {
 	openPanel("panel_snapshot_local");
 }
+
+void LLPanelSnapshotOptions::onSendToFacebook()
+{
+	LLFloaterReg::hideInstance("snapshot");
+	LLFloaterReg::showInstance("social");
+}
+
+void LLPanelSnapshotOptions::onSendToTwitter()
+{
+	LLFloaterReg::hideInstance("snapshot");
+	LLFloaterReg::showInstance("twitter");
+}
+
+void LLPanelSnapshotOptions::onSendToFlickr()
+{
+	LLFloaterReg::hideInstance("snapshot");
+	LLFloaterReg::showInstance("flickr");
+}
diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml
index 853c209bca..019ddad33c 100755
--- a/indra/newview/skins/default/xui/en/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml
@@ -10,7 +10,7 @@
  help_topic="snapshot"
  save_rect="true"
  save_visibility="false"
- title="SNAPSHOT PREVIEW"
+ title="SNAPSHOT"
  width="470">
     <floater.string
      name="unknown">
diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml
index 61c8c971c2..eff60f8228 100755
--- a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml
@@ -81,4 +81,40 @@
     <button.commit_callback
      function="Snapshot.SaveToComputer" />
   </button>
+  <text
+    font="SansSerif"
+    layout="topleft"
+    length="1"
+    follows="top|left"
+    height="16"
+    left="10"
+    name="send_to_facebook_textbox"
+    top_pad="10"
+    type="string">
+    Send to:  [secondlife:/// Facebook]
+  </text>
+  <text
+    font="SansSerif"
+    layout="topleft"
+    length="1"
+    follows="top|left"
+    height="16"
+    left="140"
+    name="send_to_twitter_textbox"
+    top_pad="-16"
+    type="string">
+    [secondlife:/// Twitter]
+  </text>
+  <text
+    font="SansSerif"
+    layout="topleft"
+    length="1"
+    follows="top|left"
+    height="16"
+    left="190"
+    name="send_to_flickr_textbox"
+    top_pad="-16"
+    type="string">
+    [secondlife:/// Flickr]
+  </text>
 </panel>
-- 
cgit v1.2.3


From dbab46ae786166ac5d6c929e2c444d8f490edd58 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Mon, 11 Nov 2013 23:13:01 +0000
Subject: made floater_snapshot links open the photo tab on the corresponding
 floater for ACME-1168

---
 indra/newview/llfloaterflickr.cpp        | 13 +++++++++++++
 indra/newview/llfloaterflickr.h          |  2 ++
 indra/newview/llfloatersocial.cpp        | 13 +++++++++++++
 indra/newview/llfloatersocial.h          |  2 ++
 indra/newview/llfloatertwitter.cpp       | 13 +++++++++++++
 indra/newview/llfloatertwitter.h         |  2 ++
 indra/newview/llpanelsnapshotoptions.cpp | 21 +++++++++++++++++++++
 7 files changed, 66 insertions(+)

diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 1edc61fcf6..7140b527b9 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -46,6 +46,7 @@
 #include "llviewerregion.h"
 #include "llviewercontrol.h"
 #include "llviewermedia.h"
+#include "lltabcontainer.h"
 
 static LLRegisterPanelClassWrapper<LLFlickrPhotoPanel> t_panel_photo("llflickrphotopanel");
 static LLRegisterPanelClassWrapper<LLFlickrAccountPanel> t_panel_account("llflickraccountpanel");
@@ -588,6 +589,18 @@ BOOL LLFloaterFlickr::postBuild()
 	return LLFloater::postBuild();
 }
 
+void LLFloaterFlickr::showPhotoPanel()
+{
+	LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mSocialPhotoPanel->getParent());
+	if (!parent)
+	{
+		llwarns << "Cannot find panel container" << llendl;
+		return;
+	}
+
+	parent->selectTabPanel(mSocialPhotoPanel);
+}
+
 // static
 void LLFloaterFlickr::preUpdate()
 {
diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h
index 8cf2cd2dd6..e9005444d8 100644
--- a/indra/newview/llfloaterflickr.h
+++ b/indra/newview/llfloaterflickr.h
@@ -110,6 +110,8 @@ public:
 	BOOL postBuild();
 	void draw();
 	void onCancel();
+	
+	void showPhotoPanel();
 
 	static void preUpdate();
 	static void postUpdate();
diff --git a/indra/newview/llfloatersocial.cpp b/indra/newview/llfloatersocial.cpp
index 2a74c8e3ea..31404da7d3 100644
--- a/indra/newview/llfloatersocial.cpp
+++ b/indra/newview/llfloatersocial.cpp
@@ -46,6 +46,7 @@
 #include "llviewerregion.h"
 #include "llviewercontrol.h"
 #include "llviewermedia.h"
+#include "lltabcontainer.h"
 
 static LLRegisterPanelClassWrapper<LLSocialStatusPanel> t_panel_status("llsocialstatuspanel");
 static LLRegisterPanelClassWrapper<LLSocialPhotoPanel> t_panel_photo("llsocialphotopanel");
@@ -823,6 +824,18 @@ BOOL LLFloaterSocial::postBuild()
 	return LLFloater::postBuild();
 }
 
+void LLFloaterSocial::showPhotoPanel()
+{
+	LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mSocialPhotoPanel->getParent());
+	if (!parent)
+	{
+		llwarns << "Cannot find panel container" << llendl;
+		return;
+	}
+
+	parent->selectTabPanel(mSocialPhotoPanel);
+}
+
 // static
 void LLFloaterSocial::preUpdate()
 {
diff --git a/indra/newview/llfloatersocial.h b/indra/newview/llfloatersocial.h
index bbe07c9704..041ae8a268 100644
--- a/indra/newview/llfloatersocial.h
+++ b/indra/newview/llfloatersocial.h
@@ -150,6 +150,8 @@ public:
 	BOOL postBuild();
 	void draw();
 	void onCancel();
+	
+	void showPhotoPanel();
 
 	static void preUpdate();
 	static void postUpdate();
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index 1324bd5fd8..0da0d64426 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -46,6 +46,7 @@
 #include "llviewerregion.h"
 #include "llviewercontrol.h"
 #include "llviewermedia.h"
+#include "lltabcontainer.h"
 
 static LLRegisterPanelClassWrapper<LLTwitterPhotoPanel> t_panel_photo("lltwitterphotopanel");
 static LLRegisterPanelClassWrapper<LLTwitterAccountPanel> t_panel_account("lltwitteraccountpanel");
@@ -565,6 +566,18 @@ BOOL LLFloaterTwitter::postBuild()
 	return LLFloater::postBuild();
 }
 
+void LLFloaterTwitter::showPhotoPanel()
+{
+	LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mSocialPhotoPanel->getParent());
+	if (!parent)
+	{
+		llwarns << "Cannot find panel container" << llendl;
+		return;
+	}
+
+	parent->selectTabPanel(mSocialPhotoPanel);
+}
+
 // static
 void LLFloaterTwitter::preUpdate()
 {
diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h
index 090e01872a..12e1d41210 100644
--- a/indra/newview/llfloatertwitter.h
+++ b/indra/newview/llfloatertwitter.h
@@ -108,6 +108,8 @@ public:
 	void draw();
 	void onCancel();
 
+	void showPhotoPanel();
+
 	static void preUpdate();
 	static void postUpdate();
 
diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp
index 1967c50a29..4cadd837d1 100755
--- a/indra/newview/llpanelsnapshotoptions.cpp
+++ b/indra/newview/llpanelsnapshotoptions.cpp
@@ -32,6 +32,9 @@
 
 #include "llfloatersnapshot.h" // FIXME: create a snapshot model
 #include "llfloaterreg.h"
+#include "llfloatersocial.h"
+#include "llfloaterflickr.h"
+#include "llfloatertwitter.h"
 
 /**
  * Provides several ways to save a snapshot.
@@ -140,17 +143,35 @@ void LLPanelSnapshotOptions::onSaveToComputer()
 void LLPanelSnapshotOptions::onSendToFacebook()
 {
 	LLFloaterReg::hideInstance("snapshot");
+
+	LLFloaterSocial* social_floater = dynamic_cast<LLFloaterSocial*>(LLFloaterReg::getInstance("social"));
+	if (social_floater)
+	{
+		social_floater->showPhotoPanel();
+	}
 	LLFloaterReg::showInstance("social");
 }
 
 void LLPanelSnapshotOptions::onSendToTwitter()
 {
 	LLFloaterReg::hideInstance("snapshot");
+
+	LLFloaterTwitter* twitter_floater = dynamic_cast<LLFloaterTwitter*>(LLFloaterReg::getInstance("twitter"));
+	if (twitter_floater)
+	{
+		twitter_floater->showPhotoPanel();
+	}
 	LLFloaterReg::showInstance("twitter");
 }
 
 void LLPanelSnapshotOptions::onSendToFlickr()
 {
 	LLFloaterReg::hideInstance("snapshot");
+
+	LLFloaterFlickr* flickr_floater = dynamic_cast<LLFloaterFlickr*>(LLFloaterReg::getInstance("flickr"));
+	if (flickr_floater)
+	{
+		flickr_floater->showPhotoPanel();
+	}
 	LLFloaterReg::showInstance("flickr");
 }
-- 
cgit v1.2.3


From 86442d1f8beae66890231c12ddc1cd9e1f1a6170 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Tue, 12 Nov 2013 01:43:00 +0000
Subject: added Flickr and Twitter FUI buttons for ACME-1179

---
 indra/newview/app_settings/commands.xml        | 20 ++++++++++++++++++++
 indra/newview/app_settings/toolbars.xml        |  2 +-
 indra/newview/skins/default/xui/en/strings.xml |  4 ++++
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index 60c942094a..6c9b67ac0b 100755
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -226,6 +226,26 @@
            is_running_function="Floater.IsOpen"
            is_running_parameters="social"
            />
+  <command name="flickr"
+           available_in_toybox="true"
+           icon="Command_Social_Icon"
+           label_ref="Command_Flickr_Label"
+           tooltip_ref="Command_Flickr_Tooltip"
+           execute_function="Floater.ToggleOrBringToFront"
+           execute_parameters="flickr"
+           is_running_function="Floater.IsOpen"
+           is_running_parameters="flickr"
+           />
+  <command name="twitter"
+           available_in_toybox="true"
+           icon="Command_Social_Icon"
+           label_ref="Command_Twitter_Label"
+           tooltip_ref="Command_Twitter_Tooltip"
+           execute_function="Floater.ToggleOrBringToFront"
+           execute_parameters="twitter"
+           is_running_function="Floater.IsOpen"
+           is_running_parameters="twitter"
+           />
   <command name="speak"
            available_in_toybox="true"
            icon="Command_Speak_Icon"
diff --git a/indra/newview/app_settings/toolbars.xml b/indra/newview/app_settings/toolbars.xml
index 86f9912815..c65b79affb 100755
--- a/indra/newview/app_settings/toolbars.xml
+++ b/indra/newview/app_settings/toolbars.xml
@@ -6,7 +6,6 @@
     <command name="speak"/>
     <command name="destinations"/>
     <command name="people"/>
-    <command name="social"/>
     <command name="profile"/>
     <command name="move"/>
     <command name="view"/>
@@ -22,5 +21,6 @@
     <command name="voice"/>
     <command name="minimap"/>
     <command name="snapshot"/>
+    <command name="social"/>
   </left_toolbar>
 </toolbars>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 2b707ed84b..b24cca588e 100755
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3893,6 +3893,8 @@ Try enclosing path to the editor with double quotes.
   <string name="Command_Search_Label">Search</string>
   <string name="Command_Snapshot_Label">Snapshot</string>
   <string name="Command_Social_Label">Facebook</string>
+  <string name="Command_Flickr_Label">Flickr</string>
+  <string name="Command_Twitter_Label">Twitter</string>
   <string name="Command_Speak_Label">Speak</string>
   <string name="Command_View_Label">Camera controls</string>
   <string name="Command_Voice_Label">Voice settings</string>
@@ -3921,6 +3923,8 @@ Try enclosing path to the editor with double quotes.
   <string name="Command_Search_Tooltip">Find places, events, people</string>
   <string name="Command_Snapshot_Tooltip">Take a picture</string>
   <string name="Command_Social_Tooltip">Post to Facebook</string>
+  <string name="Command_Flickr_Tooltip">Upload to Flickr</string>
+  <string name="Command_Twitter_Tooltip">Twitter</string>
   <string name="Command_Speak_Tooltip">Speak with people nearby using your microphone</string>
   <string name="Command_View_Tooltip">Changing camera angle</string>
   <string name="Command_Voice_Tooltip">Volume controls for calls and people near you in world</string>
-- 
cgit v1.2.3


From a718b0d182dd35bdb01973eb3108e8b4a58a627c Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Tue, 12 Nov 2013 18:04:23 +0000
Subject: updated Flickr photo upload UI content rating text for ACME-1178

---
 indra/newview/skins/default/xui/en/panel_flickr_photo.xml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
index d7d3fb6c1b..39935a7687 100644
--- a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
@@ -189,15 +189,15 @@ Use "" for multi-word tags
              height="21"
              width="250">
               <combo_box.item
-               label="Safe"
+               label="Safe content rating"
                name="SafeRating"
                value="1" />
               <combo_box.item
-               label="Moderate"
+               label="Moderate content rating"
                name="ModerateRating"
                value="2" />
               <combo_box.item
-               label="Restricted"
+               label="Restricted content rating"
                name="RestrictedRating"
                value="3" />
             </combo_box>
-- 
cgit v1.2.3


From 9946965c4decd59793adcaa39c70dbf9778d61dd Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Tue, 12 Nov 2013 20:07:54 +0000
Subject: replaced Flickr and Twitter FUI icons for ACME-1181

---
 indra/newview/app_settings/commands.xml                 |   4 ++--
 indra/newview/skins/default/textures/textures.xml       |   2 ++
 .../skins/default/textures/toolbar_icons/flickr.png     | Bin 0 -> 15530 bytes
 .../skins/default/textures/toolbar_icons/twitter.png    | Bin 0 -> 16051 bytes
 4 files changed, 4 insertions(+), 2 deletions(-)
 create mode 100644 indra/newview/skins/default/textures/toolbar_icons/flickr.png
 create mode 100644 indra/newview/skins/default/textures/toolbar_icons/twitter.png

diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index 6c9b67ac0b..f4e9cc0136 100755
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -228,7 +228,7 @@
            />
   <command name="flickr"
            available_in_toybox="true"
-           icon="Command_Social_Icon"
+           icon="Command_Flickr_Icon"
            label_ref="Command_Flickr_Label"
            tooltip_ref="Command_Flickr_Tooltip"
            execute_function="Floater.ToggleOrBringToFront"
@@ -238,7 +238,7 @@
            />
   <command name="twitter"
            available_in_toybox="true"
-           icon="Command_Social_Icon"
+           icon="Command_Twitter_Icon"
            label_ref="Command_Twitter_Label"
            tooltip_ref="Command_Twitter_Tooltip"
            execute_function="Floater.ToggleOrBringToFront"
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 94c187e21a..e42743824e 100755
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -149,6 +149,8 @@ with the same filename but different name
   <texture name="Command_Profile_Icon"      file_name="toolbar_icons/profile.png"      preload="true" />
   <texture name="Command_Search_Icon"       file_name="toolbar_icons/search.png"       preload="true" />
   <texture name="Command_Social_Icon"       file_name="toolbar_icons/facebook.png"     preload="true" />
+  <texture name="Command_Flickr_Icon"       file_name="toolbar_icons/flickr.png"     preload="true" />
+  <texture name="Command_Twitter_Icon"      file_name="toolbar_icons/twitter.png"     preload="true" />
   <texture name="Command_Snapshot_Icon"     file_name="toolbar_icons/snapshot.png"     preload="true" />
   <texture name="Command_Speak_Icon"        file_name="toolbar_icons/speak.png"        preload="true" />
   <texture name="Command_View_Icon"         file_name="toolbar_icons/view.png"         preload="true" />
diff --git a/indra/newview/skins/default/textures/toolbar_icons/flickr.png b/indra/newview/skins/default/textures/toolbar_icons/flickr.png
new file mode 100644
index 0000000000..7fce9f0df2
Binary files /dev/null and b/indra/newview/skins/default/textures/toolbar_icons/flickr.png differ
diff --git a/indra/newview/skins/default/textures/toolbar_icons/twitter.png b/indra/newview/skins/default/textures/toolbar_icons/twitter.png
new file mode 100644
index 0000000000..a99c490887
Binary files /dev/null and b/indra/newview/skins/default/textures/toolbar_icons/twitter.png differ
-- 
cgit v1.2.3


From 9e6dd1811e890d6d5e23059c67f13d9960e56366 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Tue, 12 Nov 2013 22:18:05 +0000
Subject: implemented Twitter character limits for status text box for
 ACME-1171 and ACME-1172

---
 indra/newview/llfloatertwitter.cpp                         | 13 +++++++++++++
 indra/newview/skins/default/xui/en/panel_twitter_photo.xml |  2 +-
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index 0da0d64426..46cad7ec45 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -47,6 +47,7 @@
 #include "llviewercontrol.h"
 #include "llviewermedia.h"
 #include "lltabcontainer.h"
+#include "lltexteditor.h"
 
 static LLRegisterPanelClassWrapper<LLTwitterPhotoPanel> t_panel_photo("lltwitterphotopanel");
 static LLRegisterPanelClassWrapper<LLTwitterAccountPanel> t_panel_account("lltwitteraccountpanel");
@@ -112,6 +113,18 @@ void LLTwitterPhotoPanel::draw()
 
 	bool add_photo = mPhotoCheckbox->getValue().asBoolean();
 
+	// Restrict the status text length to Twitter's character limit
+	LLTextEditor* status_text_box = dynamic_cast<LLTextEditor*>(mStatusTextBox);
+	if (status_text_box)
+	{
+		int max_status_length = add_photo ? 119 : 140;
+		status_text_box->setMaxTextLength(max_status_length);
+		if (status_text_box->getText().length() > max_status_length)
+		{
+			status_text_box->setText(status_text_box->getText().substr(0, max_status_length));
+		}
+	}
+
     // Display the preview if one is available
 	if (previewp && previewp->getThumbnailImage())
 	{
diff --git a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
index 84206c608b..fd2bffe675 100644
--- a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
@@ -31,7 +31,7 @@
            width="250"
            left="9"
            length="1"
-           max_length="700"
+           max_length="119"
            name="photo_status"
            type="string"
            word_wrap="true">
-- 
cgit v1.2.3


From 19c1be0e055bd06cb3083a9c9d126a4907a90788 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Tue, 12 Nov 2013 22:37:24 +0000
Subject: replaced Flickr title text_editor to a line_editor for ACME-1169

---
 indra/newview/skins/default/xui/en/panel_flickr_photo.xml | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
index 39935a7687..b3af271f34 100644
--- a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
@@ -102,7 +102,7 @@
              type="string">
               Title:
             </text>
-            <text_editor
+            <line_editor
              follows="left|top"
              height="20"
              width="250"
@@ -110,9 +110,8 @@
              length="1"
              max_length="256"
              name="photo_title"
-             type="string"
-             word_wrap="true">
-            </text_editor>
+             type="string">
+            </line_editor>
             <text
              length="1"
              follows="top|left|right"
-- 
cgit v1.2.3


From 47918f4537ee924c4cb9652a72561b5febbddeb6 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Wed, 13 Nov 2013 18:44:33 +0000
Subject: changed Twitter photo character limit to 100 just to be safe, and
 switched to use cap server for Flickr and Twitter service

---
 indra/newview/llflickrconnect.cpp                          | 4 ++--
 indra/newview/llfloaterflickr.cpp                          | 4 +++-
 indra/newview/llfloatertwitter.cpp                         | 2 +-
 indra/newview/lltwitterconnect.cpp                         | 4 ++--
 indra/newview/skins/default/xui/en/panel_twitter_photo.xml | 2 +-
 5 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp
index 3da3ef22b2..3a21933b63 100644
--- a/indra/newview/llflickrconnect.cpp
+++ b/indra/newview/llflickrconnect.cpp
@@ -296,8 +296,8 @@ std::string LLFlickrConnect::getFlickrConnectURL(const std::string& route, bool
     LLViewerRegion *regionp = gAgent.getRegion();
     if (regionp)
     {
-		url = "http://pdp15.lindenlab.com/flickr/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
-        //url = regionp->getCapability("FlickrConnect");
+		//url = "http://pdp15.lindenlab.com/flickr/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
+        url = regionp->getCapability("FlickrConnect");
         url += route;
     
         if (include_read_from_master && mReadFromMaster)
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 7140b527b9..0bfbd02a04 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -261,11 +261,13 @@ void LLFlickrPhotoPanel::sendPhoto()
 		// Add query parameters so Google Analytics can track incoming clicks!
 		slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS;
 
+		slurl_string = "<a href=\"" + slurl_string + "\">VISIT THIS LOCATION</a>";
+
 		// Add it to the description (pretty crude, but we don't have a better option with photos)
 		if (description.empty())
 			description = slurl_string;
 		else
-			description = description + " " + slurl_string;
+			description = description + "\n\n" + slurl_string;
 	}
 
 	// Get the content rating
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index 46cad7ec45..6f8ad109c6 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -117,7 +117,7 @@ void LLTwitterPhotoPanel::draw()
 	LLTextEditor* status_text_box = dynamic_cast<LLTextEditor*>(mStatusTextBox);
 	if (status_text_box)
 	{
-		int max_status_length = add_photo ? 119 : 140;
+		int max_status_length = add_photo ? 100 : 140;
 		status_text_box->setMaxTextLength(max_status_length);
 		if (status_text_box->getText().length() > max_status_length)
 		{
diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp
index fe45d3e4d0..e015867df2 100644
--- a/indra/newview/lltwitterconnect.cpp
+++ b/indra/newview/lltwitterconnect.cpp
@@ -296,8 +296,8 @@ std::string LLTwitterConnect::getTwitterConnectURL(const std::string& route, boo
     LLViewerRegion *regionp = gAgent.getRegion();
     if (regionp)
     {
-		url = "http://pdp15.lindenlab.com/twitter/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
-        //url = regionp->getCapability("TwitterConnect");
+		//url = "http://pdp15.lindenlab.com/twitter/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
+        url = regionp->getCapability("TwitterConnect");
         url += route;
     
         if (include_read_from_master && mReadFromMaster)
diff --git a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
index fd2bffe675..8e2412c84e 100644
--- a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
@@ -31,7 +31,7 @@
            width="250"
            left="9"
            length="1"
-           max_length="119"
+           max_length="140"
            name="photo_status"
            type="string"
            word_wrap="true">
-- 
cgit v1.2.3


From 377dd51688dea6bd83f0a9b70be12528f8a891c3 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Wed, 13 Nov 2013 20:32:06 +0000
Subject: added fancier link description text and switched back to using dev
 servers instead of caps for Flickr and Twitter

---
 indra/newview/llflickrconnect.cpp  | 4 ++--
 indra/newview/llfloaterflickr.cpp  | 3 ++-
 indra/newview/lltwitterconnect.cpp | 4 ++--
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp
index 3a21933b63..3da3ef22b2 100644
--- a/indra/newview/llflickrconnect.cpp
+++ b/indra/newview/llflickrconnect.cpp
@@ -296,8 +296,8 @@ std::string LLFlickrConnect::getFlickrConnectURL(const std::string& route, bool
     LLViewerRegion *regionp = gAgent.getRegion();
     if (regionp)
     {
-		//url = "http://pdp15.lindenlab.com/flickr/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
-        url = regionp->getCapability("FlickrConnect");
+		url = "http://pdp15.lindenlab.com/flickr/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
+        //url = regionp->getCapability("FlickrConnect");
         url += route;
     
         if (include_read_from_master && mReadFromMaster)
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 0bfbd02a04..5a05c47416 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -53,6 +53,7 @@ static LLRegisterPanelClassWrapper<LLFlickrAccountPanel> t_panel_account("llflic
 
 const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
 const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=flickr&utm_medium=photo&utm_campaign=slshare";
+const std::string DEFAULT_PHOTO_LINK_TEXT = "VISIT THIS LOCATION NOW";
 
 ///////////////////////////
 //LLFlickrPhotoPanel///////
@@ -261,7 +262,7 @@ void LLFlickrPhotoPanel::sendPhoto()
 		// Add query parameters so Google Analytics can track incoming clicks!
 		slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS;
 
-		slurl_string = "<a href=\"" + slurl_string + "\">VISIT THIS LOCATION</a>";
+		slurl_string = "<a href=\"" + slurl_string + "\">" + DEFAULT_PHOTO_LINK_TEXT + "</a>";
 
 		// Add it to the description (pretty crude, but we don't have a better option with photos)
 		if (description.empty())
diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp
index e015867df2..fe45d3e4d0 100644
--- a/indra/newview/lltwitterconnect.cpp
+++ b/indra/newview/lltwitterconnect.cpp
@@ -296,8 +296,8 @@ std::string LLTwitterConnect::getTwitterConnectURL(const std::string& route, boo
     LLViewerRegion *regionp = gAgent.getRegion();
     if (regionp)
     {
-		//url = "http://pdp15.lindenlab.com/twitter/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
-        url = regionp->getCapability("TwitterConnect");
+		url = "http://pdp15.lindenlab.com/twitter/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
+        //url = regionp->getCapability("TwitterConnect");
         url += route;
     
         if (include_read_from_master && mReadFromMaster)
-- 
cgit v1.2.3


From b267f6754efd2c77042fd4a3f6d2397eac461ce2 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Wed, 13 Nov 2013 20:39:07 +0000
Subject: included default secondlife tag in Flickr photo upload for ACME-1184

---
 indra/newview/llfloaterflickr.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 5a05c47416..97361643ed 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -54,6 +54,7 @@ static LLRegisterPanelClassWrapper<LLFlickrAccountPanel> t_panel_account("llflic
 const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
 const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=flickr&utm_medium=photo&utm_campaign=slshare";
 const std::string DEFAULT_PHOTO_LINK_TEXT = "VISIT THIS LOCATION NOW";
+const std::string DEFAULT_TAG_TEXT = "secondlife ";
 
 ///////////////////////////
 //LLFlickrPhotoPanel///////
@@ -98,6 +99,7 @@ BOOL LLFlickrPhotoPanel::postBuild()
 	mDescriptionTextBox = getChild<LLUICtrl>("photo_description");
 	mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
 	mTagsTextBox = getChild<LLUICtrl>("photo_tags");
+	mTagsTextBox->setValue(DEFAULT_TAG_TEXT);
 	mRatingComboBox = getChild<LLUICtrl>("rating_combobox");
 	mPostButton = getChild<LLUICtrl>("post_photo_btn");
 	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
@@ -287,7 +289,7 @@ void LLFlickrPhotoPanel::clearAndClose()
 {
 	mTitleTextBox->setValue("");
 	mDescriptionTextBox->setValue("");
-	mTagsTextBox->setValue("");
+	mTagsTextBox->setValue(DEFAULT_TAG_TEXT);
 
 	LLFloater* floater = getParentByType<LLFloater>();
 	if (floater)
-- 
cgit v1.2.3


From 758f656100406015bc8b27284670088decbbfabb Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Wed, 13 Nov 2013 21:38:19 +0000
Subject: made Twitter status text truncate and untruncate for ACME-1183

---
 indra/newview/llfloatertwitter.cpp | 11 ++++++++++-
 indra/newview/llfloatertwitter.h   |  2 ++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index 6f8ad109c6..06d0fb5542 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -119,9 +119,18 @@ void LLTwitterPhotoPanel::draw()
 	{
 		int max_status_length = add_photo ? 100 : 140;
 		status_text_box->setMaxTextLength(max_status_length);
+		if (!add_photo)
+		{
+			if (mOldStatusText.length() > status_text_box->getText().length() && status_text_box->getText() == mOldStatusText.substr(0, status_text_box->getText().length()))
+			{
+				status_text_box->setText(mOldStatusText);
+			}
+			mOldStatusText = "";
+		}
 		if (status_text_box->getText().length() > max_status_length)
 		{
-			status_text_box->setText(status_text_box->getText().substr(0, max_status_length));
+			mOldStatusText = status_text_box->getText();
+			status_text_box->setText(mOldStatusText.substr(0, max_status_length));
 		}
 	}
 
diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h
index 12e1d41210..686e167b1f 100644
--- a/indra/newview/llfloatertwitter.h
+++ b/indra/newview/llfloatertwitter.h
@@ -70,6 +70,8 @@ private:
 	LLUICtrl * mPhotoCheckbox;
 	LLUICtrl * mPostButton;
 	LLUICtrl* mCancelButton;
+
+	std::string mOldStatusText;
 };
 
 class LLTwitterAccountPanel : public LLPanel
-- 
cgit v1.2.3


From 08e0b94ff043b77d96609d9d8f395c0acf2640d0 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Thu, 14 Nov 2013 18:48:13 +0000
Subject: changed capitalization of Flickr SLURL link text to 'Visit this
 location now' for ACME-1186

---
 indra/newview/llfloaterflickr.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 97361643ed..61ebe563a3 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -53,7 +53,7 @@ static LLRegisterPanelClassWrapper<LLFlickrAccountPanel> t_panel_account("llflic
 
 const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
 const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=flickr&utm_medium=photo&utm_campaign=slshare";
-const std::string DEFAULT_PHOTO_LINK_TEXT = "VISIT THIS LOCATION NOW";
+const std::string DEFAULT_PHOTO_LINK_TEXT = "Visit this location now";
 const std::string DEFAULT_TAG_TEXT = "secondlife ";
 
 ///////////////////////////
-- 
cgit v1.2.3


From bf86275d78b041faffc646195bc16ecabaa3bdb7 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Tue, 26 Nov 2013 01:47:37 +0000
Subject: LLTwitterConnect and LLFlickrConnect now use caps again, instead of
 pdp15

---
 indra/newview/llflickrconnect.cpp  | 4 ++--
 indra/newview/lltwitterconnect.cpp | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp
index 3da3ef22b2..3a21933b63 100644
--- a/indra/newview/llflickrconnect.cpp
+++ b/indra/newview/llflickrconnect.cpp
@@ -296,8 +296,8 @@ std::string LLFlickrConnect::getFlickrConnectURL(const std::string& route, bool
     LLViewerRegion *regionp = gAgent.getRegion();
     if (regionp)
     {
-		url = "http://pdp15.lindenlab.com/flickr/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
-        //url = regionp->getCapability("FlickrConnect");
+		//url = "http://pdp15.lindenlab.com/flickr/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
+        url = regionp->getCapability("FlickrConnect");
         url += route;
     
         if (include_read_from_master && mReadFromMaster)
diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp
index fe45d3e4d0..e015867df2 100644
--- a/indra/newview/lltwitterconnect.cpp
+++ b/indra/newview/lltwitterconnect.cpp
@@ -296,8 +296,8 @@ std::string LLTwitterConnect::getTwitterConnectURL(const std::string& route, boo
     LLViewerRegion *regionp = gAgent.getRegion();
     if (regionp)
     {
-		url = "http://pdp15.lindenlab.com/twitter/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
-        //url = regionp->getCapability("TwitterConnect");
+		//url = "http://pdp15.lindenlab.com/twitter/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
+        url = regionp->getCapability("TwitterConnect");
         url += route;
     
         if (include_read_from_master && mReadFromMaster)
-- 
cgit v1.2.3


From ffff7ef59f43c66f966f259cb30e069a2445aa66 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 3 Dec 2013 14:22:27 -0800
Subject: ACME-1117 : Fixed crash in Facebook checkin in logged out situation,
 check presence of region before accessing it

---
 indra/newview/llfloatersocial.cpp | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llfloatersocial.cpp b/indra/newview/llfloatersocial.cpp
index 31404da7d3..e7be8cc8cc 100644
--- a/indra/newview/llfloatersocial.cpp
+++ b/indra/newview/llfloatersocial.cpp
@@ -62,9 +62,10 @@ const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_
 std::string get_map_url()
 {
     LLVector3d center_agent;
-    if (gAgent.getRegion())
+    LLViewerRegion *regionp = gAgent.getRegion();
+    if (regionp)
     {
-        center_agent = gAgent.getRegion()->getCenterGlobal();
+        center_agent = regionp->getCenterGlobal();
     }
     int x_pos = center_agent[0] / 256.0;
     int y_pos = center_agent[1] / 256.0;
@@ -607,7 +608,12 @@ void LLSocialCheckinPanel::sendCheckin()
 	slurl_string += DEFAULT_CHECKIN_QUERY_PARAMETERS;
     
 	// Get the region name
-	std::string region_name = gAgent.getRegion()->getName();
+	std::string region_name("");
+    LLViewerRegion *regionp = gAgent.getRegion();
+    if (regionp)
+    {
+        region_name = regionp->getName();
+    }
     
 	// Get the region description
 	std::string description;
-- 
cgit v1.2.3


From b6d02ae9c84e185f2507323c47c0475ce43f9e7a Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Wed, 4 Dec 2013 18:19:47 +0000
Subject: Added SLURL checkbox to floater_twitter for ACME-1216

---
 indra/newview/llfloatertwitter.cpp                 | 96 +++++++++++++++++-----
 indra/newview/llfloatertwitter.h                   |  4 +
 .../skins/default/xui/en/floater_twitter.xml       |  6 +-
 .../skins/default/xui/en/panel_twitter_photo.xml   | 14 +++-
 4 files changed, 92 insertions(+), 28 deletions(-)

diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index 06d0fb5542..ea17497d95 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -66,6 +66,7 @@ mRefreshBtn(NULL),
 mWorkingLabel(NULL),
 mThumbnailPlaceholder(NULL),
 mStatusTextBox(NULL),
+mLocationCheckbox(NULL),
 mPhotoCheckbox(NULL),
 mPostButton(NULL)
 {
@@ -92,7 +93,10 @@ BOOL LLTwitterPhotoPanel::postBuild()
     mWorkingLabel = getChild<LLUICtrl>("working_lbl");
 	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
 	mStatusTextBox = getChild<LLUICtrl>("photo_status");
+	mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
+	mLocationCheckbox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::onAddLocationToggled, this));
 	mPhotoCheckbox = getChild<LLUICtrl>("add_photo_cb");
+	mPhotoCheckbox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::onAddPhotoToggled, this));
 	mPostButton = getChild<LLUICtrl>("post_photo_btn");
 	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
 
@@ -109,30 +113,12 @@ void LLTwitterPhotoPanel::draw()
     mStatusTextBox->setEnabled(no_ongoing_connection);
     mResolutionComboBox->setEnabled(no_ongoing_connection && mPhotoCheckbox->getValue().asBoolean());
     mRefreshBtn->setEnabled(no_ongoing_connection && mPhotoCheckbox->getValue().asBoolean());
+    mLocationCheckbox->setEnabled(no_ongoing_connection);
     mPhotoCheckbox->setEnabled(no_ongoing_connection);
 
+	bool add_location = mLocationCheckbox->getValue().asBoolean();
 	bool add_photo = mPhotoCheckbox->getValue().asBoolean();
-
-	// Restrict the status text length to Twitter's character limit
-	LLTextEditor* status_text_box = dynamic_cast<LLTextEditor*>(mStatusTextBox);
-	if (status_text_box)
-	{
-		int max_status_length = add_photo ? 100 : 140;
-		status_text_box->setMaxTextLength(max_status_length);
-		if (!add_photo)
-		{
-			if (mOldStatusText.length() > status_text_box->getText().length() && status_text_box->getText() == mOldStatusText.substr(0, status_text_box->getText().length()))
-			{
-				status_text_box->setText(mOldStatusText);
-			}
-			mOldStatusText = "";
-		}
-		if (status_text_box->getText().length() > max_status_length)
-		{
-			mOldStatusText = status_text_box->getText();
-			status_text_box->setText(mOldStatusText.substr(0, max_status_length));
-		}
-	}
+	updateStatusTextLength(false);
 
     // Display the preview if one is available
 	if (previewp && previewp->getThumbnailImage())
@@ -169,7 +155,7 @@ void LLTwitterPhotoPanel::draw()
     mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate()));
     
     // Enable Post if we have a preview to send and no on going connection being processed
-    mPostButton->setEnabled(no_ongoing_connection && ((add_photo && previewp && previewp->getSnapshotUpToDate()) || !mStatusTextBox->getValue().asString().empty()));
+    mPostButton->setEnabled(no_ongoing_connection && ((add_photo && previewp && previewp->getSnapshotUpToDate()) || add_location || !mStatusTextBox->getValue().asString().empty()));
     
     // Draw the rest of the panel on top of it
 	LLPanel::draw();
@@ -213,6 +199,18 @@ void LLTwitterPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
 	}
 }
 
+void LLTwitterPhotoPanel::onAddLocationToggled()
+{
+	bool add_location = mLocationCheckbox->getValue().asBoolean();
+	updateStatusTextLength(!add_location);
+}
+
+void LLTwitterPhotoPanel::onAddPhotoToggled()
+{
+	bool add_photo = mPhotoCheckbox->getValue().asBoolean();
+	updateStatusTextLength(!add_photo);
+}
+
 void LLTwitterPhotoPanel::onClickNewSnapshot()
 {
 	LLSnapshotLivePreview* previewp = getPreviewView();
@@ -261,6 +259,26 @@ void LLTwitterPhotoPanel::sendPhoto()
 {
 	// Get the status text
 	std::string status = mStatusTextBox->getValue().asString();
+	
+	// Add the location if required
+	bool add_location = mLocationCheckbox->getValue().asBoolean();
+	if (add_location)
+	{
+		// Get the SLURL for the location
+		LLSLURL slurl;
+		LLAgentUI::buildSLURL(slurl);
+		std::string slurl_string = slurl.getSLURLString();
+
+		// Add query parameters so Google Analytics can track incoming clicks!
+		slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS;
+
+		// Add it to the status (pretty crude, but we don't have a better option with photos)
+		if (status.empty())
+			status = slurl_string;
+		else
+			status = status + " " + slurl_string;
+	}
+
 
 	// Add the photo if required
 	bool add_photo = mPhotoCheckbox->getValue().asBoolean();
@@ -292,6 +310,40 @@ void LLTwitterPhotoPanel::clearAndClose()
 	}
 }
 
+void LLTwitterPhotoPanel::updateStatusTextLength(BOOL restore_old_status_text)
+{
+	bool add_location = mLocationCheckbox->getValue().asBoolean();
+	bool add_photo = mPhotoCheckbox->getValue().asBoolean();
+
+	// Restrict the status text length to Twitter's character limit
+	LLTextEditor* status_text_box = dynamic_cast<LLTextEditor*>(mStatusTextBox);
+	if (status_text_box)
+	{
+		int max_status_length = 140 - (add_location ? 40 : 0) - (add_photo ? 40 : 0);
+		status_text_box->setMaxTextLength(max_status_length);
+		if (restore_old_status_text)
+		{
+			if (mOldStatusText.length() > status_text_box->getText().length() && status_text_box->getText() == mOldStatusText.substr(0, status_text_box->getText().length()))
+			{
+				status_text_box->setText(mOldStatusText);
+			}
+			if (mOldStatusText.length() <= max_status_length)
+			{
+				mOldStatusText = "";
+			}
+		}
+		if (status_text_box->getText().length() > max_status_length)
+		{
+			if (mOldStatusText.length() < status_text_box->getText().length() || status_text_box->getText() != mOldStatusText.substr(0, status_text_box->getText().length()))
+			{
+				mOldStatusText = status_text_box->getText();
+			}
+			status_text_box->setText(mOldStatusText.substr(0, max_status_length));
+		}
+	}
+
+}
+
 void LLTwitterPhotoPanel::updateControls()
 {
 	LLSnapshotLivePreview* previewp = getPreviewView();
diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h
index 686e167b1f..be3a099d5f 100644
--- a/indra/newview/llfloatertwitter.h
+++ b/indra/newview/llfloatertwitter.h
@@ -46,6 +46,8 @@ public:
 
 	LLSnapshotLivePreview* getPreviewView();
 	void onVisibilityChange(const LLSD& new_visibility);
+	void onAddLocationToggled();
+	void onAddPhotoToggled();
 	void onClickNewSnapshot();
 	void onSend();
 	bool onTwitterConnectStateChange(const LLSD& data);
@@ -53,6 +55,7 @@ public:
 	void sendPhoto();
 	void clearAndClose();
 
+	void updateStatusTextLength(BOOL restore_old_status_text);
 	void updateControls();
 	void updateResolution(BOOL do_update);
 	void checkAspectRatio(S32 index);
@@ -67,6 +70,7 @@ private:
 	LLUICtrl * mWorkingLabel;
 	LLUICtrl * mThumbnailPlaceholder;
 	LLUICtrl * mStatusTextBox;
+	LLUICtrl * mLocationCheckbox;
 	LLUICtrl * mPhotoCheckbox;
 	LLUICtrl * mPostButton;
 	LLUICtrl* mCancelButton;
diff --git a/indra/newview/skins/default/xui/en/floater_twitter.xml b/indra/newview/skins/default/xui/en/floater_twitter.xml
index 7007a14cdb..751914141c 100644
--- a/indra/newview/skins/default/xui/en/floater_twitter.xml
+++ b/indra/newview/skins/default/xui/en/floater_twitter.xml
@@ -10,10 +10,10 @@
   single_instance="true"
   reuse_instance="true"
   title="TWITTER"
-  height="482"
+  height="502"
   width="304">
   <panel
-   height="482"
+   height="502"
    width="304"
    visible="true"
    name="background"
@@ -27,7 +27,7 @@
      tab_height="30"
      tab_position="top"
      top="7"
-     height="437"
+     height="457"
      halign="center">
      <panel
        filename="panel_twitter_photo.xml"
diff --git a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
index 8e2412c84e..3ddec9b989 100644
--- a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
@@ -1,19 +1,19 @@
     <panel
-      height="400"
+      height="420"
       width="304"
       layout="topleft"
       name="panel_twitter_photo">
       <layout_stack
 	   layout="topleft"
        border_size="0"
-       height="392"
+       height="412"
        follows="all"
        orientation="vertical"
        name="stack_photo"
        top="8">
         <layout_panel
          name="text_panel"
-         height="140">
+         height="160">
           <text
            length="1"
            follows="top|left|right"
@@ -36,6 +36,14 @@
            type="string"
            word_wrap="true">
           </text_editor>
+          <check_box
+           follows="left|top"
+           initial_value="true"
+           label="Include SL location"
+           name="add_location_cb"
+            left="9"
+            height="16"
+           top_pad="10"/>
           <check_box
            follows="left|top"
            initial_value="true"
-- 
cgit v1.2.3


From 187fb979d365ac3052f6a95e278a1f92c3117d17 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Wed, 4 Dec 2013 19:45:26 +0000
Subject: Add character count display to floater_twitter for ACME-1215

---
 indra/newview/llfloatertwitter.cpp                         |  6 ++++++
 indra/newview/llfloatertwitter.h                           |  1 +
 indra/newview/skins/default/xui/en/panel_twitter_photo.xml | 14 ++++++++++++++
 3 files changed, 21 insertions(+)

diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index ea17497d95..82ed066b1a 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -65,6 +65,7 @@ mResolutionComboBox(NULL),
 mRefreshBtn(NULL),
 mWorkingLabel(NULL),
 mThumbnailPlaceholder(NULL),
+mStatusCounterLabel(NULL),
 mStatusTextBox(NULL),
 mLocationCheckbox(NULL),
 mPhotoCheckbox(NULL),
@@ -92,6 +93,7 @@ BOOL LLTwitterPhotoPanel::postBuild()
 	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
     mWorkingLabel = getChild<LLUICtrl>("working_lbl");
 	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
+	mStatusCounterLabel = getChild<LLUICtrl>("status_counter_label");
 	mStatusTextBox = getChild<LLUICtrl>("photo_status");
 	mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
 	mLocationCheckbox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::onAddLocationToggled, this));
@@ -340,6 +342,10 @@ void LLTwitterPhotoPanel::updateStatusTextLength(BOOL restore_old_status_text)
 			}
 			status_text_box->setText(mOldStatusText.substr(0, max_status_length));
 		}
+
+		// Update the status character counter
+		int characters_remaining = max_status_length - status_text_box->getText().length();
+		mStatusCounterLabel->setValue(characters_remaining);
 	}
 
 }
diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h
index be3a099d5f..5305143552 100644
--- a/indra/newview/llfloatertwitter.h
+++ b/indra/newview/llfloatertwitter.h
@@ -69,6 +69,7 @@ private:
 	LLUICtrl * mRefreshBtn;
 	LLUICtrl * mWorkingLabel;
 	LLUICtrl * mThumbnailPlaceholder;
+	LLUICtrl * mStatusCounterLabel;
 	LLUICtrl * mStatusTextBox;
 	LLUICtrl * mLocationCheckbox;
 	LLUICtrl * mPhotoCheckbox;
diff --git a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
index 3ddec9b989..14268c1bcf 100644
--- a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
@@ -25,6 +25,20 @@
            type="string">
             What's happening?
           </text>
+          <text
+           length="1"
+           follows="top|left"
+           font="SansSerif"
+           text_color="EmphasisColor"
+           halign="right"
+           height="16"
+           width="30"
+           left="227"
+           name="status_counter_label"
+           top="3"
+           type="string">
+            140
+          </text>
           <text_editor
            follows="left|top"
            height="87"
-- 
cgit v1.2.3


From 9108354e9d39d93dadbad34ff5ba7ecb7abc7bf9 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Thu, 5 Dec 2013 00:28:28 +0000
Subject: Renamed floater_social to floater_facebook for ACME-1205

---
 indra/newview/CMakeLists.txt                       |   4 +-
 indra/newview/app_settings/commands.xml            |  12 +-
 indra/newview/app_settings/settings.xml            |   2 +-
 indra/newview/app_settings/toolbars.xml            |   2 +-
 indra/newview/llfloaterfacebook.cpp                | 939 +++++++++++++++++++++
 indra/newview/llfloaterfacebook.h                  | 167 ++++
 indra/newview/llfloaterflickr.cpp                  |  14 +-
 indra/newview/llfloaterflickr.h                    |   2 +-
 indra/newview/llfloatersnapshot.cpp                |   6 +-
 indra/newview/llfloatersocial.cpp                  | 939 ---------------------
 indra/newview/llfloatersocial.h                    | 167 ----
 indra/newview/llfloatertwitter.cpp                 |  14 +-
 indra/newview/llfloatertwitter.h                   |   2 +-
 indra/newview/llpanelsnapshotoptions.cpp           |  10 +-
 indra/newview/llsnapshotlivepreview.cpp            |   6 +-
 indra/newview/llviewerfloaterreg.cpp               |  10 +-
 indra/newview/skins/default/textures/textures.xml  |   6 +-
 .../skins/default/xui/en/floater_facebook.xml      | 101 +++
 .../skins/default/xui/en/floater_social.xml        | 101 ---
 indra/newview/skins/default/xui/en/menu_viewer.xml |   2 +-
 .../default/xui/en/panel_facebook_account.xml      |  75 ++
 .../skins/default/xui/en/panel_facebook_photo.xml  | 152 ++++
 .../skins/default/xui/en/panel_facebook_place.xml  | 132 +++
 .../skins/default/xui/en/panel_facebook_status.xml |  67 ++
 .../skins/default/xui/en/panel_social_account.xml  |  75 --
 .../skins/default/xui/en/panel_social_photo.xml    | 152 ----
 .../skins/default/xui/en/panel_social_place.xml    | 132 ---
 .../skins/default/xui/en/panel_social_status.xml   |  67 --
 indra/newview/skins/default/xui/en/strings.xml     |  12 +-
 29 files changed, 1686 insertions(+), 1684 deletions(-)
 create mode 100644 indra/newview/llfloaterfacebook.cpp
 create mode 100644 indra/newview/llfloaterfacebook.h
 delete mode 100644 indra/newview/llfloatersocial.cpp
 delete mode 100644 indra/newview/llfloatersocial.h
 create mode 100644 indra/newview/skins/default/xui/en/floater_facebook.xml
 delete mode 100644 indra/newview/skins/default/xui/en/floater_social.xml
 create mode 100644 indra/newview/skins/default/xui/en/panel_facebook_account.xml
 create mode 100644 indra/newview/skins/default/xui/en/panel_facebook_photo.xml
 create mode 100644 indra/newview/skins/default/xui/en/panel_facebook_place.xml
 create mode 100644 indra/newview/skins/default/xui/en/panel_facebook_status.xml
 delete mode 100644 indra/newview/skins/default/xui/en/panel_social_account.xml
 delete mode 100644 indra/newview/skins/default/xui/en/panel_social_photo.xml
 delete mode 100644 indra/newview/skins/default/xui/en/panel_social_place.xml
 delete mode 100644 indra/newview/skins/default/xui/en/panel_social_status.xml

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 746991a6f0..b937d53bd8 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -229,6 +229,7 @@ set(viewer_SOURCE_FILES
     llfloatereditwater.cpp
     llfloaterenvironmentsettings.cpp
     llfloaterevent.cpp
+    llfloaterfacebook.cpp
     llfloaterflickr.cpp
     llfloaterfonttest.cpp
     llfloatergesture.cpp
@@ -276,7 +277,6 @@ set(viewer_SOURCE_FILES
     llfloatersettingsdebug.cpp
     llfloatersidepanelcontainer.cpp
     llfloatersnapshot.cpp
-    llfloatersocial.cpp
     llfloatersounddevices.cpp
     llfloaterspellchecksettings.cpp
     llfloatertelehub.cpp
@@ -821,6 +821,7 @@ set(viewer_HEADER_FILES
     llfloatereditwater.h
     llfloaterenvironmentsettings.h
     llfloaterevent.h
+    llfloaterfacebook.h
     llfloaterflickr.h
     llfloaterfonttest.h
     llfloatergesture.h
@@ -868,7 +869,6 @@ set(viewer_HEADER_FILES
     llfloatersettingsdebug.h
     llfloatersidepanelcontainer.h
     llfloatersnapshot.h
-    llfloatersocial.h
     llfloatersounddevices.h
     llfloaterspellchecksettings.h
     llfloatertelehub.h
diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index f4e9cc0136..7b329e2092 100755
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -216,15 +216,15 @@
            is_running_function="Floater.IsOpen"
            is_running_parameters="snapshot"
            />
-  <command name="social"
+  <command name="facebook"
            available_in_toybox="true"
-           icon="Command_Social_Icon"
-           label_ref="Command_Social_Label"
-           tooltip_ref="Command_Social_Tooltip"
+           icon="Command_Facebook_Icon"
+           label_ref="Command_Facebook_Label"
+           tooltip_ref="Command_Facebook_Tooltip"
            execute_function="Floater.ToggleOrBringToFront"
-           execute_parameters="social"
+           execute_parameters="facebook"
            is_running_function="Floater.IsOpen"
-           is_running_parameters="social"
+           is_running_parameters="facebook"
            />
   <command name="flickr"
            available_in_toybox="true"
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 41aac583d7..0f60fc0210 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -13108,7 +13108,7 @@
     <key>SocialPhotoResolution</key>
     <map>
       <key>Comment</key>
-      <string>Default resolution when sharing photo using the social floater</string>
+      <string>Default resolution when sharing photo using the social floaters</string>
       <key>Persist</key>
       <integer>1</integer>
       <key>Type</key>
diff --git a/indra/newview/app_settings/toolbars.xml b/indra/newview/app_settings/toolbars.xml
index c65b79affb..d61aee9a14 100755
--- a/indra/newview/app_settings/toolbars.xml
+++ b/indra/newview/app_settings/toolbars.xml
@@ -21,6 +21,6 @@
     <command name="voice"/>
     <command name="minimap"/>
     <command name="snapshot"/>
-    <command name="social"/>
+    <command name="facebook"/>
   </left_toolbar>
 </toolbars>
diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
new file mode 100644
index 0000000000..6488e7ea00
--- /dev/null
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -0,0 +1,939 @@
+/** 
+* @file llfloaterfacebook.cpp
+* @brief Implementation of llfloaterfacebook
+* @author Gilbert@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterfacebook.h"
+
+#include "llagent.h"
+#include "llagentui.h"
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "llfacebookconnect.h"
+#include "llfloaterreg.h"
+#include "lliconctrl.h"
+#include "llresmgr.h"		// LLLocale
+#include "llsdserialize.h"
+#include "llloadingindicator.h"
+#include "llplugincookiestore.h"
+#include "llslurl.h"
+#include "lltrans.h"
+#include "llsnapshotlivepreview.h"
+#include "llviewerregion.h"
+#include "llviewercontrol.h"
+#include "llviewermedia.h"
+#include "lltabcontainer.h"
+
+static LLRegisterPanelClassWrapper<LLFacebookStatusPanel> t_panel_status("llfacebookstatuspanel");
+static LLRegisterPanelClassWrapper<LLFacebookPhotoPanel> t_panel_photo("llfacebookphotopanel");
+static LLRegisterPanelClassWrapper<LLFacebookCheckinPanel> t_panel_checkin("llfacebookcheckinpanel");
+static LLRegisterPanelClassWrapper<LLFacebookAccountPanel> t_panel_account("llfacebookaccountpanel");
+
+const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
+const std::string DEFAULT_CHECKIN_LOCATION_URL = "http://maps.secondlife.com/";
+const std::string DEFAULT_CHECKIN_ICON_URL = "http://map.secondlife.com.s3.amazonaws.com/map_placeholder.png";
+const std::string DEFAULT_CHECKIN_QUERY_PARAMETERS = "?sourceid=slshare_checkin&utm_source=facebook&utm_medium=checkin&utm_campaign=slshare";
+const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=facebook&utm_medium=photo&utm_campaign=slshare";
+
+std::string get_map_url()
+{
+    LLVector3d center_agent;
+    LLViewerRegion *regionp = gAgent.getRegion();
+    if (regionp)
+    {
+        center_agent = regionp->getCenterGlobal();
+    }
+    int x_pos = center_agent[0] / 256.0;
+    int y_pos = center_agent[1] / 256.0;
+    std::string map_url = gSavedSettings.getString("CurrentMapServerURL") + llformat("map-1-%d-%d-objects.jpg", x_pos, y_pos);
+    return map_url;
+}
+
+///////////////////////////
+//LLFacebookStatusPanel//////
+///////////////////////////
+
+LLFacebookStatusPanel::LLFacebookStatusPanel() :
+	mMessageTextEditor(NULL),
+	mPostButton(NULL),
+    mCancelButton(NULL)
+{
+	mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLFacebookStatusPanel::onSend, this));
+}
+
+BOOL LLFacebookStatusPanel::postBuild()
+{
+	mMessageTextEditor = getChild<LLUICtrl>("status_message");
+	mPostButton = getChild<LLUICtrl>("post_status_btn");
+	mCancelButton = getChild<LLUICtrl>("cancel_status_btn");
+
+	return LLPanel::postBuild();
+}
+
+void LLFacebookStatusPanel::draw()
+{
+    if (mMessageTextEditor && mPostButton && mCancelButton)
+	{
+        bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing());
+        std::string message = mMessageTextEditor->getValue().asString();
+        mMessageTextEditor->setEnabled(no_ongoing_connection);
+        mCancelButton->setEnabled(no_ongoing_connection);
+        mPostButton->setEnabled(no_ongoing_connection && !message.empty());
+    }
+
+	LLPanel::draw();
+}
+
+void LLFacebookStatusPanel::onSend()
+{
+	LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel"); // just in case it is already listening
+	LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookStatusPanel", boost::bind(&LLFacebookStatusPanel::onFacebookConnectStateChange, this, _1));
+		
+	// Connect to Facebook if necessary and then post
+	if (LLFacebookConnect::instance().isConnected())
+	{
+		sendStatus();
+	}
+	else
+	{
+		LLFacebookConnect::instance().checkConnectionToFacebook(true);
+	}
+}
+
+bool LLFacebookStatusPanel::onFacebookConnectStateChange(const LLSD& data)
+{
+	switch (data.get("enum").asInteger())
+	{
+		case LLFacebookConnect::FB_CONNECTED:
+			sendStatus();
+			break;
+
+		case LLFacebookConnect::FB_POSTED:
+			LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookStatusPanel");
+			clearAndClose();
+			break;
+	}
+
+	return false;
+}
+
+void LLFacebookStatusPanel::sendStatus()
+{
+	std::string message = mMessageTextEditor->getValue().asString();
+	if (!message.empty())
+	{
+		LLFacebookConnect::instance().updateStatus(message);
+	}
+}
+
+void LLFacebookStatusPanel::clearAndClose()
+{
+	mMessageTextEditor->setValue("");
+
+	LLFloater* floater = getParentByType<LLFloater>();
+	if (floater)
+	{
+		floater->closeFloater();
+	}
+}
+
+///////////////////////////
+//LLFacebookPhotoPanel///////
+///////////////////////////
+
+LLFacebookPhotoPanel::LLFacebookPhotoPanel() :
+mSnapshotPanel(NULL),
+mResolutionComboBox(NULL),
+mRefreshBtn(NULL),
+mWorkingLabel(NULL),
+mThumbnailPlaceholder(NULL),
+mCaptionTextBox(NULL),
+mLocationCheckbox(NULL),
+mPostButton(NULL)
+{
+	mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFacebookPhotoPanel::onSend, this));
+	mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFacebookPhotoPanel::onClickNewSnapshot, this));
+}
+
+LLFacebookPhotoPanel::~LLFacebookPhotoPanel()
+{
+	if(mPreviewHandle.get())
+	{
+		mPreviewHandle.get()->die();
+	}
+}
+
+BOOL LLFacebookPhotoPanel::postBuild()
+{
+	setVisibleCallback(boost::bind(&LLFacebookPhotoPanel::onVisibilityChange, this, _2));
+	
+	mSnapshotPanel = getChild<LLUICtrl>("snapshot_panel");
+	mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
+	mResolutionComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE));
+	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
+    mWorkingLabel = getChild<LLUICtrl>("working_lbl");
+	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
+	mCaptionTextBox = getChild<LLUICtrl>("photo_caption");
+	mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
+	mPostButton = getChild<LLUICtrl>("post_photo_btn");
+	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
+
+	return LLPanel::postBuild();
+}
+
+void LLFacebookPhotoPanel::draw()
+{ 
+	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
+
+    // Enable interaction only if no transaction with the service is on-going (prevent duplicated posts)
+    bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing());
+    mCancelButton->setEnabled(no_ongoing_connection);
+    mCaptionTextBox->setEnabled(no_ongoing_connection);
+    mResolutionComboBox->setEnabled(no_ongoing_connection);
+    mRefreshBtn->setEnabled(no_ongoing_connection);
+    mLocationCheckbox->setEnabled(no_ongoing_connection);
+    
+    // Display the preview if one is available
+	if (previewp && previewp->getThumbnailImage())
+	{
+		const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect();
+		const S32 thumbnail_w = previewp->getThumbnailWidth();
+		const S32 thumbnail_h = previewp->getThumbnailHeight();
+
+		// calc preview offset within the preview rect
+		const S32 local_offset_x = (thumbnail_rect.getWidth()  - thumbnail_w) / 2 ;
+		const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ;
+
+		// calc preview offset within the floater rect
+        // Hack : To get the full offset, we need to take into account each and every offset of each widgets up to the floater.
+        // This is almost as arbitrary as using a fixed offset so that's what we do here for the sake of simplicity.
+        // *TODO : Get the offset looking through the hierarchy of widgets, should be done in postBuild() so to avoid traversing the hierarchy each time.
+		S32 offset_x = thumbnail_rect.mLeft + local_offset_x - 1;
+		S32 offset_y = thumbnail_rect.mBottom + local_offset_y - 39;
+        
+		mSnapshotPanel->localPointToOtherView(offset_x, offset_y, &offset_x, &offset_y, getParentByType<LLFloater>());
+        
+		gGL.matrixMode(LLRender::MM_MODELVIEW);
+		// Apply floater transparency to the texture unless the floater is focused.
+		F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
+		LLColor4 color = LLColor4::white;
+		gl_draw_scaled_image(offset_x, offset_y, 
+			thumbnail_w, thumbnail_h,
+			previewp->getThumbnailImage(), color % alpha);
+
+		previewp->drawPreviewRect(offset_x, offset_y) ;
+	}
+
+    // Update the visibility of the working (computing preview) label
+    mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate()));
+    
+    // Enable Post if we have a preview to send and no on going connection being processed
+    mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()));
+    
+    // Draw the rest of the panel on top of it
+	LLPanel::draw();
+}
+
+LLSnapshotLivePreview* LLFacebookPhotoPanel::getPreviewView()
+{
+	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get();
+	return previewp;
+}
+
+void LLFacebookPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
+{
+	bool visible = new_visibility.asBoolean();
+	if (visible)
+	{
+		if (mPreviewHandle.get())
+		{
+			LLSnapshotLivePreview* preview = getPreviewView();
+			if(preview)
+			{
+				lldebugs << "opened, updating snapshot" << llendl;
+				preview->updateSnapshot(TRUE);
+			}
+		}
+		else
+		{
+			LLRect full_screen_rect = getRootView()->getRect();
+			LLSnapshotLivePreview::Params p;
+			p.rect(full_screen_rect);
+			LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
+			mPreviewHandle = previewp->getHandle();	
+
+			previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
+			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
+			//previewp->setSnapshotQuality(98);
+			previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
+
+			updateControls();
+		}
+	}
+}
+
+void LLFacebookPhotoPanel::onClickNewSnapshot()
+{
+	LLSnapshotLivePreview* previewp = getPreviewView();
+	if (previewp)
+	{
+		//setStatus(Impl::STATUS_READY);
+		lldebugs << "updating snapshot" << llendl;
+		previewp->updateSnapshot(TRUE);
+	}
+}
+
+void LLFacebookPhotoPanel::onSend()
+{
+	LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel"); // just in case it is already listening
+	LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookPhotoPanel", boost::bind(&LLFacebookPhotoPanel::onFacebookConnectStateChange, this, _1));
+	
+	// Connect to Facebook if necessary and then post
+	if (LLFacebookConnect::instance().isConnected())
+	{
+		sendPhoto();
+	}
+	else
+	{
+		LLFacebookConnect::instance().checkConnectionToFacebook(true);
+	}
+}
+
+bool LLFacebookPhotoPanel::onFacebookConnectStateChange(const LLSD& data)
+{
+	switch (data.get("enum").asInteger())
+	{
+		case LLFacebookConnect::FB_CONNECTED:
+			sendPhoto();
+			break;
+
+		case LLFacebookConnect::FB_POSTED:
+			LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel");
+			clearAndClose();
+			break;
+	}
+
+	return false;
+}
+
+void LLFacebookPhotoPanel::sendPhoto()
+{
+	// Get the caption
+	std::string caption = mCaptionTextBox->getValue().asString();
+
+	// Add the location if required
+	bool add_location = mLocationCheckbox->getValue().asBoolean();
+	if (add_location)
+	{
+		// Get the SLURL for the location
+		LLSLURL slurl;
+		LLAgentUI::buildSLURL(slurl);
+		std::string slurl_string = slurl.getSLURLString();
+
+		// Add query parameters so Google Analytics can track incoming clicks!
+		slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS;
+
+		// Add it to the caption (pretty crude, but we don't have a better option with photos)
+		if (caption.empty())
+			caption = slurl_string;
+		else
+			caption = caption + " " + slurl_string;
+	}
+
+	// Get the image
+	LLSnapshotLivePreview* previewp = getPreviewView();
+	
+	// Post to Facebook
+	LLFacebookConnect::instance().sharePhoto(previewp->getFormattedImage(), caption);
+
+	updateControls();
+}
+
+void LLFacebookPhotoPanel::clearAndClose()
+{
+	mCaptionTextBox->setValue("");
+
+	LLFloater* floater = getParentByType<LLFloater>();
+	if (floater)
+	{
+		floater->closeFloater();
+	}
+}
+
+void LLFacebookPhotoPanel::updateControls()
+{
+	LLSnapshotLivePreview* previewp = getPreviewView();
+	BOOL got_bytes = previewp && previewp->getDataSize() > 0;
+	BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
+	LLSnapshotLivePreview::ESnapshotType shot_type = (previewp ? previewp->getSnapshotType() : LLSnapshotLivePreview::SNAPSHOT_POSTCARD);
+
+	// *TODO: Separate maximum size for Web images from postcards
+	lldebugs << "Is snapshot up-to-date? " << got_snap << llendl;
+
+	LLLocale locale(LLLocale::USER_LOCALE);
+	std::string bytes_string;
+	if (got_snap)
+	{
+		LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 );
+	}
+
+	//getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown")); <---uses localized string
+	getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : "unknown");
+	getChild<LLUICtrl>("file_size_label")->setColor(
+		shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD 
+		&& got_bytes
+		&& previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" ));
+
+	updateResolution(FALSE);
+}
+
+void LLFacebookPhotoPanel::updateResolution(BOOL do_update)
+{
+	LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox);
+
+	std::string sdstring = combobox->getSelectedValue();
+	LLSD sdres;
+	std::stringstream sstream(sdstring);
+	LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
+
+	S32 width = sdres[0];
+	S32 height = sdres[1];
+
+	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
+	if (previewp && combobox->getCurrentIndex() >= 0)
+	{
+		S32 original_width = 0 , original_height = 0 ;
+		previewp->getSize(original_width, original_height) ;
+
+		if (width == 0 || height == 0)
+		{
+			// take resolution from current window size
+			lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl;
+			previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
+		}
+		else
+		{
+			// use the resolution from the selected pre-canned drop-down choice
+			lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl;
+			previewp->setSize(width, height);
+		}
+
+		checkAspectRatio(width);
+
+		previewp->getSize(width, height);
+		
+		if(original_width != width || original_height != height)
+		{
+			previewp->setSize(width, height);
+
+			// hide old preview as the aspect ratio could be wrong
+			lldebugs << "updating thumbnail" << llendl;
+			
+			previewp->updateSnapshot(FALSE, TRUE);
+			if(do_update)
+			{
+				lldebugs << "Will update controls" << llendl;
+				updateControls();
+                LLFacebookPhotoPanel::onClickNewSnapshot();
+			}
+		}
+		
+	}
+}
+
+void LLFacebookPhotoPanel::checkAspectRatio(S32 index)
+{
+	LLSnapshotLivePreview *previewp = getPreviewView() ;
+
+	BOOL keep_aspect = FALSE;
+
+	if (0 == index) // current window size
+	{
+		keep_aspect = TRUE;
+	}
+	else // predefined resolution
+	{
+		keep_aspect = FALSE;
+	}
+
+	if (previewp)
+	{
+		previewp->mKeepAspectRatio = keep_aspect;
+	}
+}
+
+LLUICtrl* LLFacebookPhotoPanel::getRefreshBtn()
+{
+	return mRefreshBtn;
+}
+
+////////////////////////
+//LLFacebookCheckinPanel//
+////////////////////////
+
+LLFacebookCheckinPanel::LLFacebookCheckinPanel() :
+    mMapUrl(""),
+    mReloadingMapTexture(false)
+{
+	mCommitCallbackRegistrar.add("SocialSharing.SendCheckin", boost::bind(&LLFacebookCheckinPanel::onSend, this));
+}
+
+BOOL LLFacebookCheckinPanel::postBuild()
+{
+    // Keep pointers to widgets so we don't traverse the UI hierarchy too often
+	mPostButton = getChild<LLUICtrl>("post_place_btn");
+	mCancelButton = getChild<LLUICtrl>("cancel_place_btn");
+	mMessageTextEditor = getChild<LLUICtrl>("place_caption");
+    mMapLoadingIndicator = getChild<LLUICtrl>("map_loading_indicator");
+    mMapPlaceholder = getChild<LLIconCtrl>("map_placeholder");
+    mMapDefault = getChild<LLIconCtrl>("map_default");
+    mMapCheckBox = getChild<LLCheckBoxCtrl>("add_place_view_cb");
+    
+	return LLPanel::postBuild();
+}
+
+void LLFacebookCheckinPanel::draw()
+{
+    bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing());
+    mPostButton->setEnabled(no_ongoing_connection);
+    mCancelButton->setEnabled(no_ongoing_connection);
+    mMessageTextEditor->setEnabled(no_ongoing_connection);
+    mMapCheckBox->setEnabled(no_ongoing_connection);
+
+    std::string map_url = get_map_url();
+    // Did we change location?
+    if (map_url != mMapUrl)
+    {
+        mMapUrl = map_url;
+        // Load the map tile
+        mMapTexture = LLViewerTextureManager::getFetchedTextureFromUrl(mMapUrl, FTT_MAP_TILE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+        mMapTexture->setBoostLevel(LLGLTexture::BOOST_MAP);
+        mReloadingMapTexture = true;
+        // In the meantime, put the "loading" indicator on, hide the tile map and disable the checkbox
+        mMapLoadingIndicator->setVisible(true);
+        mMapPlaceholder->setVisible(false);
+    }
+    // Are we done loading the map tile?
+    if (mReloadingMapTexture && mMapTexture->isFullyLoaded())
+    {
+        // Don't do it again next time around
+        mReloadingMapTexture = false;
+        // Convert the map texture to the appropriate image object
+        LLPointer<LLUIImage> ui_image = new LLUIImage(mMapUrl, mMapTexture);
+        // Load the map widget with the correct map tile image
+        mMapPlaceholder->setImage(ui_image);
+        // Now hide the loading indicator, bring the tile in view and reenable the checkbox with its previous value
+        mMapLoadingIndicator->setVisible(false);
+        mMapPlaceholder->setVisible(true);
+    }
+    // Show the default icon if that's the checkbox value (the real one...)
+    // This will hide/show the loading indicator and/or tile underneath
+    mMapDefault->setVisible(!(mMapCheckBox->get()));
+
+	LLPanel::draw();
+}
+
+void LLFacebookCheckinPanel::onSend()
+{
+	LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel"); // just in case it is already listening
+	LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookCheckinPanel", boost::bind(&LLFacebookCheckinPanel::onFacebookConnectStateChange, this, _1));
+	
+	// Connect to Facebook if necessary and then post
+	if (LLFacebookConnect::instance().isConnected())
+	{
+		sendCheckin();
+	}
+	else
+	{
+		LLFacebookConnect::instance().checkConnectionToFacebook(true);
+	}
+}
+
+bool LLFacebookCheckinPanel::onFacebookConnectStateChange(const LLSD& data)
+{
+	switch (data.get("enum").asInteger())
+	{
+		case LLFacebookConnect::FB_CONNECTED:
+			sendCheckin();
+			break;
+
+		case LLFacebookConnect::FB_POSTED:
+			LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookCheckinPanel");
+			clearAndClose();
+			break;
+	}
+
+	return false;
+}
+
+void LLFacebookCheckinPanel::sendCheckin()
+{
+	// Get the location SLURL
+	LLSLURL slurl;
+	LLAgentUI::buildSLURL(slurl);
+	std::string slurl_string = slurl.getSLURLString();
+
+	// Use a valid http:// URL if the scheme is secondlife:// 
+	LLURI slurl_uri(slurl_string);
+	if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME)
+	{
+		slurl_string = DEFAULT_CHECKIN_LOCATION_URL;
+	}
+
+	// Add query parameters so Google Analytics can track incoming clicks!
+	slurl_string += DEFAULT_CHECKIN_QUERY_PARAMETERS;
+    
+	// Get the region name
+	std::string region_name("");
+    LLViewerRegion *regionp = gAgent.getRegion();
+    if (regionp)
+    {
+        region_name = regionp->getName();
+    }
+    
+	// Get the region description
+	std::string description;
+	LLAgentUI::buildLocationString(description, LLAgentUI::LOCATION_FORMAT_NORMAL_COORDS, gAgent.getPositionAgent());
+    
+	// Optionally add the region map view
+	bool add_map_view = mMapCheckBox->getValue().asBoolean();
+    std::string map_url = (add_map_view ? get_map_url() : DEFAULT_CHECKIN_ICON_URL);
+    
+	// Get the caption
+	std::string caption = mMessageTextEditor->getValue().asString();
+
+	// Post to Facebook
+	LLFacebookConnect::instance().postCheckin(slurl_string, region_name, description, map_url, caption);
+}
+
+void LLFacebookCheckinPanel::clearAndClose()
+{
+	mMessageTextEditor->setValue("");
+
+	LLFloater* floater = getParentByType<LLFloater>();
+	if (floater)
+	{
+		floater->closeFloater();
+	}
+}
+
+///////////////////////////
+//LLFacebookAccountPanel//////
+///////////////////////////
+
+LLFacebookAccountPanel::LLFacebookAccountPanel() : 
+mAccountCaptionLabel(NULL),
+mAccountNameLabel(NULL),
+mPanelButtons(NULL),
+mConnectButton(NULL),
+mDisconnectButton(NULL)
+{
+	mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFacebookAccountPanel::onConnect, this));
+	mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFacebookAccountPanel::onDisconnect, this));
+
+	setVisibleCallback(boost::bind(&LLFacebookAccountPanel::onVisibilityChange, this, _2));
+}
+
+BOOL LLFacebookAccountPanel::postBuild()
+{
+	mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label");
+	mAccountNameLabel = getChild<LLTextBox>("account_name_label");
+	mPanelButtons = getChild<LLUICtrl>("panel_buttons");
+	mConnectButton = getChild<LLUICtrl>("connect_btn");
+	mDisconnectButton = getChild<LLUICtrl>("disconnect_btn");
+
+	return LLPanel::postBuild();
+}
+
+void LLFacebookAccountPanel::draw()
+{
+	LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState();
+
+	//Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress
+	bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING;
+	mDisconnectButton->setEnabled(!disconnecting);
+
+	//Disable the 'connect' button when a connection is in progress
+	bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS;
+	mConnectButton->setEnabled(!connecting);
+
+	LLPanel::draw();
+}
+
+void LLFacebookAccountPanel::onVisibilityChange(const LLSD& new_visibility)
+{
+	bool visible = new_visibility.asBoolean();
+
+	if(visible)
+	{
+		LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel");
+		LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookAccountPanel::onFacebookConnectStateChange, this, _1));
+
+		LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel");
+		LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLFacebookAccountPanel", boost::bind(&LLFacebookAccountPanel::onFacebookConnectInfoChange, this));
+
+		//Connected
+		if(LLFacebookConnect::instance().isConnected())
+		{
+			showConnectedLayout();
+		}
+		//Check if connected (show disconnected layout in meantime)
+		else
+		{
+			showDisconnectedLayout();
+		}
+        if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) ||
+            (LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED))
+        {
+            LLFacebookConnect::instance().checkConnectionToFacebook();
+        }
+	}
+	else
+	{
+		LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel");
+		LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLFacebookAccountPanel");
+	}
+}
+
+bool LLFacebookAccountPanel::onFacebookConnectStateChange(const LLSD& data)
+{
+	if(LLFacebookConnect::instance().isConnected())
+	{
+		//In process of disconnecting so leave the layout as is
+		if(data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING)
+		{
+			showConnectedLayout();
+		}
+	}
+	else
+	{
+		showDisconnectedLayout();
+	}
+
+	return false;
+}
+
+bool LLFacebookAccountPanel::onFacebookConnectInfoChange()
+{
+	LLSD info = LLFacebookConnect::instance().getInfo();
+	std::string clickable_name;
+
+	//Strings of format [http://www.somewebsite.com Click Me] become clickable text
+	if(info.has("link") && info.has("name"))
+	{
+		clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]";
+	}
+
+	mAccountNameLabel->setText(clickable_name);
+
+	return false;
+}
+
+void LLFacebookAccountPanel::showConnectButton()
+{
+	if(!mConnectButton->getVisible())
+	{
+		mConnectButton->setVisible(TRUE);
+		mDisconnectButton->setVisible(FALSE);
+	}
+}
+
+void LLFacebookAccountPanel::hideConnectButton()
+{
+	if(mConnectButton->getVisible())
+	{
+		mConnectButton->setVisible(FALSE);
+		mDisconnectButton->setVisible(TRUE);
+	}
+}
+
+void LLFacebookAccountPanel::showDisconnectedLayout()
+{
+	mAccountCaptionLabel->setText(getString("facebook_disconnected"));
+	mAccountNameLabel->setText(std::string(""));
+	showConnectButton();
+}
+
+void LLFacebookAccountPanel::showConnectedLayout()
+{
+	LLFacebookConnect::instance().loadFacebookInfo();
+
+	mAccountCaptionLabel->setText(getString("facebook_connected"));
+	hideConnectButton();
+}
+
+void LLFacebookAccountPanel::onConnect()
+{
+	LLFacebookConnect::instance().checkConnectionToFacebook(true);
+
+	//Clear only the facebook browser cookies so that the facebook login screen appears
+	LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); 
+}
+
+void LLFacebookAccountPanel::onDisconnect()
+{
+	LLFacebookConnect::instance().disconnectFromFacebook();
+
+	LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); 
+}
+
+////////////////////////
+//LLFloaterFacebook///////
+////////////////////////
+
+LLFloaterFacebook::LLFloaterFacebook(const LLSD& key) : LLFloater(key),
+    mFacebookPhotoPanel(NULL),
+    mStatusErrorText(NULL),
+    mStatusLoadingText(NULL),
+    mStatusLoadingIndicator(NULL)
+{
+	mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterFacebook::onCancel, this));
+}
+
+void LLFloaterFacebook::onCancel()
+{
+    closeFloater();
+}
+
+BOOL LLFloaterFacebook::postBuild()
+{
+    // Keep tab of the Photo Panel
+	mFacebookPhotoPanel = static_cast<LLFacebookPhotoPanel*>(getChild<LLUICtrl>("panel_facebook_photo"));
+    // Connection status widgets
+    mStatusErrorText = getChild<LLTextBox>("connection_error_text");
+    mStatusLoadingText = getChild<LLTextBox>("connection_loading_text");
+    mStatusLoadingIndicator = getChild<LLUICtrl>("connection_loading_indicator");
+	return LLFloater::postBuild();
+}
+
+void LLFloaterFacebook::showPhotoPanel()
+{
+	LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mFacebookPhotoPanel->getParent());
+	if (!parent)
+	{
+		llwarns << "Cannot find panel container" << llendl;
+		return;
+	}
+
+	parent->selectTabPanel(mFacebookPhotoPanel);
+}
+
+// static
+void LLFloaterFacebook::preUpdate()
+{
+	LLFloaterFacebook* instance = LLFloaterReg::findTypedInstance<LLFloaterFacebook>("facebook");
+	if (instance)
+	{
+		//Will set file size text to 'unknown'
+		instance->mFacebookPhotoPanel->updateControls();
+	}
+}
+
+// static
+void LLFloaterFacebook::postUpdate()
+{
+	LLFloaterFacebook* instance = LLFloaterReg::findTypedInstance<LLFloaterFacebook>("facebook");
+	if (instance)
+	{
+		//Will set the file size text
+		instance->mFacebookPhotoPanel->updateControls();
+
+		// The refresh button is initially hidden. We show it after the first update,
+		// i.e. after snapshot is taken
+		LLUICtrl * refresh_button = instance->mFacebookPhotoPanel->getRefreshBtn();
+
+		if (!refresh_button->getVisible())
+		{
+			refresh_button->setVisible(true);
+		}
+		
+	}
+}
+
+void LLFloaterFacebook::draw()
+{
+    if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator)
+    {
+        mStatusErrorText->setVisible(false);
+        mStatusLoadingText->setVisible(false);
+        mStatusLoadingIndicator->setVisible(false);
+        LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState();
+        std::string status_text;
+        
+        switch (connection_state)
+        {
+        case LLFacebookConnect::FB_NOT_CONNECTED:
+            // No status displayed when first opening the panel and no connection done
+        case LLFacebookConnect::FB_CONNECTED:
+            // When successfully connected, no message is displayed
+        case LLFacebookConnect::FB_POSTED:
+            // No success message to show since we actually close the floater after successful posting completion
+            break;
+        case LLFacebookConnect::FB_CONNECTION_IN_PROGRESS:
+            // Connection loading indicator
+            mStatusLoadingText->setVisible(true);
+            status_text = LLTrans::getString("SocialFacebookConnecting");
+            mStatusLoadingText->setValue(status_text);
+            mStatusLoadingIndicator->setVisible(true);
+            break;
+        case LLFacebookConnect::FB_POSTING:
+            // Posting indicator
+            mStatusLoadingText->setVisible(true);
+            status_text = LLTrans::getString("SocialFacebookPosting");
+            mStatusLoadingText->setValue(status_text);
+            mStatusLoadingIndicator->setVisible(true);
+			break;
+        case LLFacebookConnect::FB_CONNECTION_FAILED:
+            // Error connecting to the service
+            mStatusErrorText->setVisible(true);
+            status_text = LLTrans::getString("SocialFacebookErrorConnecting");
+            mStatusErrorText->setValue(status_text);
+            break;
+        case LLFacebookConnect::FB_POST_FAILED:
+            // Error posting to the service
+            mStatusErrorText->setVisible(true);
+            status_text = LLTrans::getString("SocialFacebookErrorPosting");
+            mStatusErrorText->setValue(status_text);
+            break;
+		case LLFacebookConnect::FB_DISCONNECTING:
+			// Disconnecting loading indicator
+			mStatusLoadingText->setVisible(true);
+			status_text = LLTrans::getString("SocialFacebookDisconnecting");
+			mStatusLoadingText->setValue(status_text);
+			mStatusLoadingIndicator->setVisible(true);
+			break;
+		case LLFacebookConnect::FB_DISCONNECT_FAILED:
+			// Error disconnecting from the service
+			mStatusErrorText->setVisible(true);
+			status_text = LLTrans::getString("SocialFacebookErrorDisconnecting");
+			mStatusErrorText->setValue(status_text);
+			break;
+        }
+    }
+	LLFloater::draw();
+}
+
diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h
new file mode 100644
index 0000000000..ab6420264b
--- /dev/null
+++ b/indra/newview/llfloaterfacebook.h
@@ -0,0 +1,167 @@
+/** 
+* @file   llfloaterfacebook.h
+* @brief  Header file for llfloaterfacebook
+* @author Gilbert@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+#ifndef LL_LLFLOATERFACEBOOK_H
+#define LL_LLFLOATERFACEBOOK_H
+
+#include "llfloater.h"
+#include "lltextbox.h"
+#include "llviewertexture.h"
+
+class LLIconCtrl;
+class LLCheckBoxCtrl;
+class LLSnapshotLivePreview;
+
+class LLFacebookStatusPanel : public LLPanel
+{
+public:
+    LLFacebookStatusPanel();
+	BOOL postBuild();
+	void draw();
+    void onSend();
+	bool onFacebookConnectStateChange(const LLSD& data);
+
+	void sendStatus();
+	void clearAndClose();
+
+private:
+	LLUICtrl* mMessageTextEditor;
+	LLUICtrl* mPostButton;
+	LLUICtrl* mCancelButton;
+};
+
+class LLFacebookPhotoPanel : public LLPanel
+{
+public:
+	LLFacebookPhotoPanel();
+	~LLFacebookPhotoPanel();
+
+	BOOL postBuild();
+	void draw();
+
+	LLSnapshotLivePreview* getPreviewView();
+	void onVisibilityChange(const LLSD& new_visibility);
+	void onClickNewSnapshot();
+	void onSend();
+	bool onFacebookConnectStateChange(const LLSD& data);
+
+	void sendPhoto();
+	void clearAndClose();
+
+	void updateControls();
+	void updateResolution(BOOL do_update);
+	void checkAspectRatio(S32 index);
+	LLUICtrl* getRefreshBtn();
+
+private:
+	LLHandle<LLView> mPreviewHandle;
+
+	LLUICtrl * mSnapshotPanel;
+	LLUICtrl * mResolutionComboBox;
+	LLUICtrl * mRefreshBtn;
+	LLUICtrl * mWorkingLabel;
+	LLUICtrl * mThumbnailPlaceholder;
+	LLUICtrl * mCaptionTextBox;
+	LLUICtrl * mLocationCheckbox;
+	LLUICtrl * mPostButton;
+	LLUICtrl* mCancelButton;
+};
+
+class LLFacebookCheckinPanel : public LLPanel
+{
+public:
+    LLFacebookCheckinPanel();
+	BOOL postBuild();
+	void draw();
+    void onSend();
+	bool onFacebookConnectStateChange(const LLSD& data);
+
+	void sendCheckin();
+	void clearAndClose();
+
+private:
+    std::string mMapUrl;
+    LLPointer<LLViewerFetchedTexture> mMapTexture;
+	LLUICtrl* mPostButton;
+	LLUICtrl* mCancelButton;
+	LLUICtrl* mMessageTextEditor;
+    LLUICtrl* mMapLoadingIndicator;
+    LLIconCtrl* mMapPlaceholder;
+    LLIconCtrl* mMapDefault;
+    LLCheckBoxCtrl* mMapCheckBox;
+    bool mReloadingMapTexture;
+};
+
+class LLFacebookAccountPanel : public LLPanel
+{
+public:
+	LLFacebookAccountPanel();
+	BOOL postBuild();
+	void draw();
+
+private:
+	void onVisibilityChange(const LLSD& new_visibility);
+	bool onFacebookConnectStateChange(const LLSD& data);
+	bool onFacebookConnectInfoChange();
+	void onConnect();
+	void onUseAnotherAccount();
+	void onDisconnect();
+
+	void showConnectButton();
+	void hideConnectButton();
+	void showDisconnectedLayout();
+	void showConnectedLayout();
+
+	LLTextBox * mAccountCaptionLabel;
+	LLTextBox * mAccountNameLabel;
+	LLUICtrl * mPanelButtons;
+	LLUICtrl * mConnectButton;
+	LLUICtrl * mDisconnectButton;
+};
+
+
+class LLFloaterFacebook : public LLFloater
+{
+public:
+	LLFloaterFacebook(const LLSD& key);
+	BOOL postBuild();
+	void draw();
+	void onCancel();
+	
+	void showPhotoPanel();
+
+	static void preUpdate();
+	static void postUpdate();
+
+private:
+	LLFacebookPhotoPanel* mFacebookPhotoPanel;
+    LLTextBox* mStatusErrorText;
+    LLTextBox* mStatusLoadingText;
+    LLUICtrl*  mStatusLoadingIndicator;
+};
+
+#endif // LL_LLFLOATERFACEBOOK_H
+
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 61ebe563a3..0a4c3f091b 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -570,7 +570,7 @@ void LLFlickrAccountPanel::onDisconnect()
 ////////////////////////
 
 LLFloaterFlickr::LLFloaterFlickr(const LLSD& key) : LLFloater(key),
-    mSocialPhotoPanel(NULL),
+    mFlickrPhotoPanel(NULL),
     mStatusErrorText(NULL),
     mStatusLoadingText(NULL),
     mStatusLoadingIndicator(NULL)
@@ -586,7 +586,7 @@ void LLFloaterFlickr::onCancel()
 BOOL LLFloaterFlickr::postBuild()
 {
     // Keep tab of the Photo Panel
-	mSocialPhotoPanel = static_cast<LLFlickrPhotoPanel*>(getChild<LLUICtrl>("panel_flickr_photo"));
+	mFlickrPhotoPanel = static_cast<LLFlickrPhotoPanel*>(getChild<LLUICtrl>("panel_flickr_photo"));
     // Connection status widgets
     mStatusErrorText = getChild<LLTextBox>("connection_error_text");
     mStatusLoadingText = getChild<LLTextBox>("connection_loading_text");
@@ -596,14 +596,14 @@ BOOL LLFloaterFlickr::postBuild()
 
 void LLFloaterFlickr::showPhotoPanel()
 {
-	LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mSocialPhotoPanel->getParent());
+	LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mFlickrPhotoPanel->getParent());
 	if (!parent)
 	{
 		llwarns << "Cannot find panel container" << llendl;
 		return;
 	}
 
-	parent->selectTabPanel(mSocialPhotoPanel);
+	parent->selectTabPanel(mFlickrPhotoPanel);
 }
 
 // static
@@ -613,7 +613,7 @@ void LLFloaterFlickr::preUpdate()
 	if (instance)
 	{
 		//Will set file size text to 'unknown'
-		instance->mSocialPhotoPanel->updateControls();
+		instance->mFlickrPhotoPanel->updateControls();
 	}
 }
 
@@ -624,11 +624,11 @@ void LLFloaterFlickr::postUpdate()
 	if (instance)
 	{
 		//Will set the file size text
-		instance->mSocialPhotoPanel->updateControls();
+		instance->mFlickrPhotoPanel->updateControls();
 
 		// The refresh button is initially hidden. We show it after the first update,
 		// i.e. after snapshot is taken
-		LLUICtrl * refresh_button = instance->mSocialPhotoPanel->getRefreshBtn();
+		LLUICtrl * refresh_button = instance->mFlickrPhotoPanel->getRefreshBtn();
 
 		if (!refresh_button->getVisible())
 		{
diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h
index e9005444d8..9a329d4451 100644
--- a/indra/newview/llfloaterflickr.h
+++ b/indra/newview/llfloaterflickr.h
@@ -117,7 +117,7 @@ public:
 	static void postUpdate();
 
 private:
-	LLFlickrPhotoPanel* mSocialPhotoPanel;
+	LLFlickrPhotoPanel* mFlickrPhotoPanel;
     LLTextBox* mStatusErrorText;
     LLTextBox* mStatusLoadingText;
     LLUICtrl*  mStatusLoadingIndicator;
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 4701e128d3..c3efc26991 100755
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -31,7 +31,7 @@
 #include "llagent.h"
 #include "llfacebookconnect.h"
 #include "llfloaterreg.h"
-#include "llfloatersocial.h"
+#include "llfloaterfacebook.h"
 #include "llfloaterflickr.h"
 #include "llfloatertwitter.h"
 #include "llcheckboxctrl.h"
@@ -1266,11 +1266,11 @@ S32 LLFloaterSnapshot::notify(const LLSD& info)
 void LLFloaterSnapshot::update()
 {
 	LLFloaterSnapshot* inst = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot");
-	LLFloaterSocial* floater_social = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social"); 
+	LLFloaterFacebook* floater_facebook = LLFloaterReg::findTypedInstance<LLFloaterFacebook>("facebook"); 
 	LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr"); 
 	LLFloaterTwitter* floater_twitter = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter"); 
 
-	if (!inst && !floater_social && !floater_flickr && !floater_twitter)
+	if (!inst && !floater_facebook && !floater_flickr && !floater_twitter)
 		return;
 	
 	BOOL changed = FALSE;
diff --git a/indra/newview/llfloatersocial.cpp b/indra/newview/llfloatersocial.cpp
deleted file mode 100644
index e7be8cc8cc..0000000000
--- a/indra/newview/llfloatersocial.cpp
+++ /dev/null
@@ -1,939 +0,0 @@
-/** 
-* @file llfloatersocial.cpp
-* @brief Implementation of llfloatersocial
-* @author Gilbert@lindenlab.com
-*
-* $LicenseInfo:firstyear=2013&license=viewerlgpl$
-* Second Life Viewer Source Code
-* Copyright (C) 2013, Linden Research, Inc.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser General Public
-* License as published by the Free Software Foundation;
-* version 2.1 of the License only.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this library; if not, write to the Free Software
-* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*
-* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
-* $/LicenseInfo$
-*/
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llfloatersocial.h"
-
-#include "llagent.h"
-#include "llagentui.h"
-#include "llcheckboxctrl.h"
-#include "llcombobox.h"
-#include "llfacebookconnect.h"
-#include "llfloaterreg.h"
-#include "lliconctrl.h"
-#include "llresmgr.h"		// LLLocale
-#include "llsdserialize.h"
-#include "llloadingindicator.h"
-#include "llplugincookiestore.h"
-#include "llslurl.h"
-#include "lltrans.h"
-#include "llsnapshotlivepreview.h"
-#include "llviewerregion.h"
-#include "llviewercontrol.h"
-#include "llviewermedia.h"
-#include "lltabcontainer.h"
-
-static LLRegisterPanelClassWrapper<LLSocialStatusPanel> t_panel_status("llsocialstatuspanel");
-static LLRegisterPanelClassWrapper<LLSocialPhotoPanel> t_panel_photo("llsocialphotopanel");
-static LLRegisterPanelClassWrapper<LLSocialCheckinPanel> t_panel_checkin("llsocialcheckinpanel");
-static LLRegisterPanelClassWrapper<LLSocialAccountPanel> t_panel_account("llsocialaccountpanel");
-
-const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
-const std::string DEFAULT_CHECKIN_LOCATION_URL = "http://maps.secondlife.com/";
-const std::string DEFAULT_CHECKIN_ICON_URL = "http://map.secondlife.com.s3.amazonaws.com/map_placeholder.png";
-const std::string DEFAULT_CHECKIN_QUERY_PARAMETERS = "?sourceid=slshare_checkin&utm_source=facebook&utm_medium=checkin&utm_campaign=slshare";
-const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=facebook&utm_medium=photo&utm_campaign=slshare";
-
-std::string get_map_url()
-{
-    LLVector3d center_agent;
-    LLViewerRegion *regionp = gAgent.getRegion();
-    if (regionp)
-    {
-        center_agent = regionp->getCenterGlobal();
-    }
-    int x_pos = center_agent[0] / 256.0;
-    int y_pos = center_agent[1] / 256.0;
-    std::string map_url = gSavedSettings.getString("CurrentMapServerURL") + llformat("map-1-%d-%d-objects.jpg", x_pos, y_pos);
-    return map_url;
-}
-
-///////////////////////////
-//LLSocialStatusPanel//////
-///////////////////////////
-
-LLSocialStatusPanel::LLSocialStatusPanel() :
-	mMessageTextEditor(NULL),
-	mPostButton(NULL),
-    mCancelButton(NULL)
-{
-	mCommitCallbackRegistrar.add("SocialSharing.SendStatus", boost::bind(&LLSocialStatusPanel::onSend, this));
-}
-
-BOOL LLSocialStatusPanel::postBuild()
-{
-	mMessageTextEditor = getChild<LLUICtrl>("status_message");
-	mPostButton = getChild<LLUICtrl>("post_status_btn");
-	mCancelButton = getChild<LLUICtrl>("cancel_status_btn");
-
-	return LLPanel::postBuild();
-}
-
-void LLSocialStatusPanel::draw()
-{
-    if (mMessageTextEditor && mPostButton && mCancelButton)
-	{
-        bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing());
-        std::string message = mMessageTextEditor->getValue().asString();
-        mMessageTextEditor->setEnabled(no_ongoing_connection);
-        mCancelButton->setEnabled(no_ongoing_connection);
-        mPostButton->setEnabled(no_ongoing_connection && !message.empty());
-    }
-
-	LLPanel::draw();
-}
-
-void LLSocialStatusPanel::onSend()
-{
-	LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialStatusPanel"); // just in case it is already listening
-	LLEventPumps::instance().obtain("FacebookConnectState").listen("LLSocialStatusPanel", boost::bind(&LLSocialStatusPanel::onFacebookConnectStateChange, this, _1));
-		
-	// Connect to Facebook if necessary and then post
-	if (LLFacebookConnect::instance().isConnected())
-	{
-		sendStatus();
-	}
-	else
-	{
-		LLFacebookConnect::instance().checkConnectionToFacebook(true);
-	}
-}
-
-bool LLSocialStatusPanel::onFacebookConnectStateChange(const LLSD& data)
-{
-	switch (data.get("enum").asInteger())
-	{
-		case LLFacebookConnect::FB_CONNECTED:
-			sendStatus();
-			break;
-
-		case LLFacebookConnect::FB_POSTED:
-			LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialStatusPanel");
-			clearAndClose();
-			break;
-	}
-
-	return false;
-}
-
-void LLSocialStatusPanel::sendStatus()
-{
-	std::string message = mMessageTextEditor->getValue().asString();
-	if (!message.empty())
-	{
-		LLFacebookConnect::instance().updateStatus(message);
-	}
-}
-
-void LLSocialStatusPanel::clearAndClose()
-{
-	mMessageTextEditor->setValue("");
-
-	LLFloater* floater = getParentByType<LLFloater>();
-	if (floater)
-	{
-		floater->closeFloater();
-	}
-}
-
-///////////////////////////
-//LLSocialPhotoPanel///////
-///////////////////////////
-
-LLSocialPhotoPanel::LLSocialPhotoPanel() :
-mSnapshotPanel(NULL),
-mResolutionComboBox(NULL),
-mRefreshBtn(NULL),
-mWorkingLabel(NULL),
-mThumbnailPlaceholder(NULL),
-mCaptionTextBox(NULL),
-mLocationCheckbox(NULL),
-mPostButton(NULL)
-{
-	mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLSocialPhotoPanel::onSend, this));
-	mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLSocialPhotoPanel::onClickNewSnapshot, this));
-}
-
-LLSocialPhotoPanel::~LLSocialPhotoPanel()
-{
-	if(mPreviewHandle.get())
-	{
-		mPreviewHandle.get()->die();
-	}
-}
-
-BOOL LLSocialPhotoPanel::postBuild()
-{
-	setVisibleCallback(boost::bind(&LLSocialPhotoPanel::onVisibilityChange, this, _2));
-	
-	mSnapshotPanel = getChild<LLUICtrl>("snapshot_panel");
-	mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
-	mResolutionComboBox->setCommitCallback(boost::bind(&LLSocialPhotoPanel::updateResolution, this, TRUE));
-	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
-    mWorkingLabel = getChild<LLUICtrl>("working_lbl");
-	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
-	mCaptionTextBox = getChild<LLUICtrl>("photo_caption");
-	mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
-	mPostButton = getChild<LLUICtrl>("post_photo_btn");
-	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
-
-	return LLPanel::postBuild();
-}
-
-void LLSocialPhotoPanel::draw()
-{ 
-	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
-
-    // Enable interaction only if no transaction with the service is on-going (prevent duplicated posts)
-    bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing());
-    mCancelButton->setEnabled(no_ongoing_connection);
-    mCaptionTextBox->setEnabled(no_ongoing_connection);
-    mResolutionComboBox->setEnabled(no_ongoing_connection);
-    mRefreshBtn->setEnabled(no_ongoing_connection);
-    mLocationCheckbox->setEnabled(no_ongoing_connection);
-    
-    // Display the preview if one is available
-	if (previewp && previewp->getThumbnailImage())
-	{
-		const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect();
-		const S32 thumbnail_w = previewp->getThumbnailWidth();
-		const S32 thumbnail_h = previewp->getThumbnailHeight();
-
-		// calc preview offset within the preview rect
-		const S32 local_offset_x = (thumbnail_rect.getWidth()  - thumbnail_w) / 2 ;
-		const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ;
-
-		// calc preview offset within the floater rect
-        // Hack : To get the full offset, we need to take into account each and every offset of each widgets up to the floater.
-        // This is almost as arbitrary as using a fixed offset so that's what we do here for the sake of simplicity.
-        // *TODO : Get the offset looking through the hierarchy of widgets, should be done in postBuild() so to avoid traversing the hierarchy each time.
-		S32 offset_x = thumbnail_rect.mLeft + local_offset_x - 1;
-		S32 offset_y = thumbnail_rect.mBottom + local_offset_y - 39;
-        
-		mSnapshotPanel->localPointToOtherView(offset_x, offset_y, &offset_x, &offset_y, getParentByType<LLFloater>());
-        
-		gGL.matrixMode(LLRender::MM_MODELVIEW);
-		// Apply floater transparency to the texture unless the floater is focused.
-		F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
-		LLColor4 color = LLColor4::white;
-		gl_draw_scaled_image(offset_x, offset_y, 
-			thumbnail_w, thumbnail_h,
-			previewp->getThumbnailImage(), color % alpha);
-
-		previewp->drawPreviewRect(offset_x, offset_y) ;
-	}
-
-    // Update the visibility of the working (computing preview) label
-    mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate()));
-    
-    // Enable Post if we have a preview to send and no on going connection being processed
-    mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()));
-    
-    // Draw the rest of the panel on top of it
-	LLPanel::draw();
-}
-
-LLSnapshotLivePreview* LLSocialPhotoPanel::getPreviewView()
-{
-	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get();
-	return previewp;
-}
-
-void LLSocialPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
-{
-	bool visible = new_visibility.asBoolean();
-	if (visible)
-	{
-		if (mPreviewHandle.get())
-		{
-			LLSnapshotLivePreview* preview = getPreviewView();
-			if(preview)
-			{
-				lldebugs << "opened, updating snapshot" << llendl;
-				preview->updateSnapshot(TRUE);
-			}
-		}
-		else
-		{
-			LLRect full_screen_rect = getRootView()->getRect();
-			LLSnapshotLivePreview::Params p;
-			p.rect(full_screen_rect);
-			LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
-			mPreviewHandle = previewp->getHandle();	
-
-			previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
-			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
-			//previewp->setSnapshotQuality(98);
-			previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
-
-			updateControls();
-		}
-	}
-}
-
-void LLSocialPhotoPanel::onClickNewSnapshot()
-{
-	LLSnapshotLivePreview* previewp = getPreviewView();
-	if (previewp)
-	{
-		//setStatus(Impl::STATUS_READY);
-		lldebugs << "updating snapshot" << llendl;
-		previewp->updateSnapshot(TRUE);
-	}
-}
-
-void LLSocialPhotoPanel::onSend()
-{
-	LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialPhotoPanel"); // just in case it is already listening
-	LLEventPumps::instance().obtain("FacebookConnectState").listen("LLSocialPhotoPanel", boost::bind(&LLSocialPhotoPanel::onFacebookConnectStateChange, this, _1));
-	
-	// Connect to Facebook if necessary and then post
-	if (LLFacebookConnect::instance().isConnected())
-	{
-		sendPhoto();
-	}
-	else
-	{
-		LLFacebookConnect::instance().checkConnectionToFacebook(true);
-	}
-}
-
-bool LLSocialPhotoPanel::onFacebookConnectStateChange(const LLSD& data)
-{
-	switch (data.get("enum").asInteger())
-	{
-		case LLFacebookConnect::FB_CONNECTED:
-			sendPhoto();
-			break;
-
-		case LLFacebookConnect::FB_POSTED:
-			LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialPhotoPanel");
-			clearAndClose();
-			break;
-	}
-
-	return false;
-}
-
-void LLSocialPhotoPanel::sendPhoto()
-{
-	// Get the caption
-	std::string caption = mCaptionTextBox->getValue().asString();
-
-	// Add the location if required
-	bool add_location = mLocationCheckbox->getValue().asBoolean();
-	if (add_location)
-	{
-		// Get the SLURL for the location
-		LLSLURL slurl;
-		LLAgentUI::buildSLURL(slurl);
-		std::string slurl_string = slurl.getSLURLString();
-
-		// Add query parameters so Google Analytics can track incoming clicks!
-		slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS;
-
-		// Add it to the caption (pretty crude, but we don't have a better option with photos)
-		if (caption.empty())
-			caption = slurl_string;
-		else
-			caption = caption + " " + slurl_string;
-	}
-
-	// Get the image
-	LLSnapshotLivePreview* previewp = getPreviewView();
-	
-	// Post to Facebook
-	LLFacebookConnect::instance().sharePhoto(previewp->getFormattedImage(), caption);
-
-	updateControls();
-}
-
-void LLSocialPhotoPanel::clearAndClose()
-{
-	mCaptionTextBox->setValue("");
-
-	LLFloater* floater = getParentByType<LLFloater>();
-	if (floater)
-	{
-		floater->closeFloater();
-	}
-}
-
-void LLSocialPhotoPanel::updateControls()
-{
-	LLSnapshotLivePreview* previewp = getPreviewView();
-	BOOL got_bytes = previewp && previewp->getDataSize() > 0;
-	BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
-	LLSnapshotLivePreview::ESnapshotType shot_type = (previewp ? previewp->getSnapshotType() : LLSnapshotLivePreview::SNAPSHOT_POSTCARD);
-
-	// *TODO: Separate maximum size for Web images from postcards
-	lldebugs << "Is snapshot up-to-date? " << got_snap << llendl;
-
-	LLLocale locale(LLLocale::USER_LOCALE);
-	std::string bytes_string;
-	if (got_snap)
-	{
-		LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 );
-	}
-
-	//getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown")); <---uses localized string
-	getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : "unknown");
-	getChild<LLUICtrl>("file_size_label")->setColor(
-		shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD 
-		&& got_bytes
-		&& previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" ));
-
-	updateResolution(FALSE);
-}
-
-void LLSocialPhotoPanel::updateResolution(BOOL do_update)
-{
-	LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox);
-
-	std::string sdstring = combobox->getSelectedValue();
-	LLSD sdres;
-	std::stringstream sstream(sdstring);
-	LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
-
-	S32 width = sdres[0];
-	S32 height = sdres[1];
-
-	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
-	if (previewp && combobox->getCurrentIndex() >= 0)
-	{
-		S32 original_width = 0 , original_height = 0 ;
-		previewp->getSize(original_width, original_height) ;
-
-		if (width == 0 || height == 0)
-		{
-			// take resolution from current window size
-			lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl;
-			previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
-		}
-		else
-		{
-			// use the resolution from the selected pre-canned drop-down choice
-			lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl;
-			previewp->setSize(width, height);
-		}
-
-		checkAspectRatio(width);
-
-		previewp->getSize(width, height);
-		
-		if(original_width != width || original_height != height)
-		{
-			previewp->setSize(width, height);
-
-			// hide old preview as the aspect ratio could be wrong
-			lldebugs << "updating thumbnail" << llendl;
-			
-			previewp->updateSnapshot(FALSE, TRUE);
-			if(do_update)
-			{
-				lldebugs << "Will update controls" << llendl;
-				updateControls();
-                LLSocialPhotoPanel::onClickNewSnapshot();
-			}
-		}
-		
-	}
-}
-
-void LLSocialPhotoPanel::checkAspectRatio(S32 index)
-{
-	LLSnapshotLivePreview *previewp = getPreviewView() ;
-
-	BOOL keep_aspect = FALSE;
-
-	if (0 == index) // current window size
-	{
-		keep_aspect = TRUE;
-	}
-	else // predefined resolution
-	{
-		keep_aspect = FALSE;
-	}
-
-	if (previewp)
-	{
-		previewp->mKeepAspectRatio = keep_aspect;
-	}
-}
-
-LLUICtrl* LLSocialPhotoPanel::getRefreshBtn()
-{
-	return mRefreshBtn;
-}
-
-////////////////////////
-//LLSocialCheckinPanel//
-////////////////////////
-
-LLSocialCheckinPanel::LLSocialCheckinPanel() :
-    mMapUrl(""),
-    mReloadingMapTexture(false)
-{
-	mCommitCallbackRegistrar.add("SocialSharing.SendCheckin", boost::bind(&LLSocialCheckinPanel::onSend, this));
-}
-
-BOOL LLSocialCheckinPanel::postBuild()
-{
-    // Keep pointers to widgets so we don't traverse the UI hierarchy too often
-	mPostButton = getChild<LLUICtrl>("post_place_btn");
-	mCancelButton = getChild<LLUICtrl>("cancel_place_btn");
-	mMessageTextEditor = getChild<LLUICtrl>("place_caption");
-    mMapLoadingIndicator = getChild<LLUICtrl>("map_loading_indicator");
-    mMapPlaceholder = getChild<LLIconCtrl>("map_placeholder");
-    mMapDefault = getChild<LLIconCtrl>("map_default");
-    mMapCheckBox = getChild<LLCheckBoxCtrl>("add_place_view_cb");
-    
-	return LLPanel::postBuild();
-}
-
-void LLSocialCheckinPanel::draw()
-{
-    bool no_ongoing_connection = !(LLFacebookConnect::instance().isTransactionOngoing());
-    mPostButton->setEnabled(no_ongoing_connection);
-    mCancelButton->setEnabled(no_ongoing_connection);
-    mMessageTextEditor->setEnabled(no_ongoing_connection);
-    mMapCheckBox->setEnabled(no_ongoing_connection);
-
-    std::string map_url = get_map_url();
-    // Did we change location?
-    if (map_url != mMapUrl)
-    {
-        mMapUrl = map_url;
-        // Load the map tile
-        mMapTexture = LLViewerTextureManager::getFetchedTextureFromUrl(mMapUrl, FTT_MAP_TILE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
-        mMapTexture->setBoostLevel(LLGLTexture::BOOST_MAP);
-        mReloadingMapTexture = true;
-        // In the meantime, put the "loading" indicator on, hide the tile map and disable the checkbox
-        mMapLoadingIndicator->setVisible(true);
-        mMapPlaceholder->setVisible(false);
-    }
-    // Are we done loading the map tile?
-    if (mReloadingMapTexture && mMapTexture->isFullyLoaded())
-    {
-        // Don't do it again next time around
-        mReloadingMapTexture = false;
-        // Convert the map texture to the appropriate image object
-        LLPointer<LLUIImage> ui_image = new LLUIImage(mMapUrl, mMapTexture);
-        // Load the map widget with the correct map tile image
-        mMapPlaceholder->setImage(ui_image);
-        // Now hide the loading indicator, bring the tile in view and reenable the checkbox with its previous value
-        mMapLoadingIndicator->setVisible(false);
-        mMapPlaceholder->setVisible(true);
-    }
-    // Show the default icon if that's the checkbox value (the real one...)
-    // This will hide/show the loading indicator and/or tile underneath
-    mMapDefault->setVisible(!(mMapCheckBox->get()));
-
-	LLPanel::draw();
-}
-
-void LLSocialCheckinPanel::onSend()
-{
-	LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialCheckinPanel"); // just in case it is already listening
-	LLEventPumps::instance().obtain("FacebookConnectState").listen("LLSocialCheckinPanel", boost::bind(&LLSocialCheckinPanel::onFacebookConnectStateChange, this, _1));
-	
-	// Connect to Facebook if necessary and then post
-	if (LLFacebookConnect::instance().isConnected())
-	{
-		sendCheckin();
-	}
-	else
-	{
-		LLFacebookConnect::instance().checkConnectionToFacebook(true);
-	}
-}
-
-bool LLSocialCheckinPanel::onFacebookConnectStateChange(const LLSD& data)
-{
-	switch (data.get("enum").asInteger())
-	{
-		case LLFacebookConnect::FB_CONNECTED:
-			sendCheckin();
-			break;
-
-		case LLFacebookConnect::FB_POSTED:
-			LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialCheckinPanel");
-			clearAndClose();
-			break;
-	}
-
-	return false;
-}
-
-void LLSocialCheckinPanel::sendCheckin()
-{
-	// Get the location SLURL
-	LLSLURL slurl;
-	LLAgentUI::buildSLURL(slurl);
-	std::string slurl_string = slurl.getSLURLString();
-
-	// Use a valid http:// URL if the scheme is secondlife:// 
-	LLURI slurl_uri(slurl_string);
-	if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME)
-	{
-		slurl_string = DEFAULT_CHECKIN_LOCATION_URL;
-	}
-
-	// Add query parameters so Google Analytics can track incoming clicks!
-	slurl_string += DEFAULT_CHECKIN_QUERY_PARAMETERS;
-    
-	// Get the region name
-	std::string region_name("");
-    LLViewerRegion *regionp = gAgent.getRegion();
-    if (regionp)
-    {
-        region_name = regionp->getName();
-    }
-    
-	// Get the region description
-	std::string description;
-	LLAgentUI::buildLocationString(description, LLAgentUI::LOCATION_FORMAT_NORMAL_COORDS, gAgent.getPositionAgent());
-    
-	// Optionally add the region map view
-	bool add_map_view = mMapCheckBox->getValue().asBoolean();
-    std::string map_url = (add_map_view ? get_map_url() : DEFAULT_CHECKIN_ICON_URL);
-    
-	// Get the caption
-	std::string caption = mMessageTextEditor->getValue().asString();
-
-	// Post to Facebook
-	LLFacebookConnect::instance().postCheckin(slurl_string, region_name, description, map_url, caption);
-}
-
-void LLSocialCheckinPanel::clearAndClose()
-{
-	mMessageTextEditor->setValue("");
-
-	LLFloater* floater = getParentByType<LLFloater>();
-	if (floater)
-	{
-		floater->closeFloater();
-	}
-}
-
-///////////////////////////
-//LLSocialAccountPanel//////
-///////////////////////////
-
-LLSocialAccountPanel::LLSocialAccountPanel() : 
-mAccountCaptionLabel(NULL),
-mAccountNameLabel(NULL),
-mPanelButtons(NULL),
-mConnectButton(NULL),
-mDisconnectButton(NULL)
-{
-	mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLSocialAccountPanel::onConnect, this));
-	mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLSocialAccountPanel::onDisconnect, this));
-
-	setVisibleCallback(boost::bind(&LLSocialAccountPanel::onVisibilityChange, this, _2));
-}
-
-BOOL LLSocialAccountPanel::postBuild()
-{
-	mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label");
-	mAccountNameLabel = getChild<LLTextBox>("account_name_label");
-	mPanelButtons = getChild<LLUICtrl>("panel_buttons");
-	mConnectButton = getChild<LLUICtrl>("connect_btn");
-	mDisconnectButton = getChild<LLUICtrl>("disconnect_btn");
-
-	return LLPanel::postBuild();
-}
-
-void LLSocialAccountPanel::draw()
-{
-	LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState();
-
-	//Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress
-	bool disconnecting = connection_state == LLFacebookConnect::FB_DISCONNECTING;
-	mDisconnectButton->setEnabled(!disconnecting);
-
-	//Disable the 'connect' button when a connection is in progress
-	bool connecting = connection_state == LLFacebookConnect::FB_CONNECTION_IN_PROGRESS;
-	mConnectButton->setEnabled(!connecting);
-
-	LLPanel::draw();
-}
-
-void LLSocialAccountPanel::onVisibilityChange(const LLSD& new_visibility)
-{
-	bool visible = new_visibility.asBoolean();
-
-	if(visible)
-	{
-		LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialAccountPanel");
-		LLEventPumps::instance().obtain("FacebookConnectState").listen("LLSocialAccountPanel", boost::bind(&LLSocialAccountPanel::onFacebookConnectStateChange, this, _1));
-
-		LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLSocialAccountPanel");
-		LLEventPumps::instance().obtain("FacebookConnectInfo").listen("LLSocialAccountPanel", boost::bind(&LLSocialAccountPanel::onFacebookConnectInfoChange, this));
-
-		//Connected
-		if(LLFacebookConnect::instance().isConnected())
-		{
-			showConnectedLayout();
-		}
-		//Check if connected (show disconnected layout in meantime)
-		else
-		{
-			showDisconnectedLayout();
-		}
-        if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) ||
-            (LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED))
-        {
-            LLFacebookConnect::instance().checkConnectionToFacebook();
-        }
-	}
-	else
-	{
-		LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLSocialAccountPanel");
-		LLEventPumps::instance().obtain("FacebookConnectInfo").stopListening("LLSocialAccountPanel");
-	}
-}
-
-bool LLSocialAccountPanel::onFacebookConnectStateChange(const LLSD& data)
-{
-	if(LLFacebookConnect::instance().isConnected())
-	{
-		//In process of disconnecting so leave the layout as is
-		if(data.get("enum").asInteger() != LLFacebookConnect::FB_DISCONNECTING)
-		{
-			showConnectedLayout();
-		}
-	}
-	else
-	{
-		showDisconnectedLayout();
-	}
-
-	return false;
-}
-
-bool LLSocialAccountPanel::onFacebookConnectInfoChange()
-{
-	LLSD info = LLFacebookConnect::instance().getInfo();
-	std::string clickable_name;
-
-	//Strings of format [http://www.somewebsite.com Click Me] become clickable text
-	if(info.has("link") && info.has("name"))
-	{
-		clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]";
-	}
-
-	mAccountNameLabel->setText(clickable_name);
-
-	return false;
-}
-
-void LLSocialAccountPanel::showConnectButton()
-{
-	if(!mConnectButton->getVisible())
-	{
-		mConnectButton->setVisible(TRUE);
-		mDisconnectButton->setVisible(FALSE);
-	}
-}
-
-void LLSocialAccountPanel::hideConnectButton()
-{
-	if(mConnectButton->getVisible())
-	{
-		mConnectButton->setVisible(FALSE);
-		mDisconnectButton->setVisible(TRUE);
-	}
-}
-
-void LLSocialAccountPanel::showDisconnectedLayout()
-{
-	mAccountCaptionLabel->setText(getString("facebook_disconnected"));
-	mAccountNameLabel->setText(std::string(""));
-	showConnectButton();
-}
-
-void LLSocialAccountPanel::showConnectedLayout()
-{
-	LLFacebookConnect::instance().loadFacebookInfo();
-
-	mAccountCaptionLabel->setText(getString("facebook_connected"));
-	hideConnectButton();
-}
-
-void LLSocialAccountPanel::onConnect()
-{
-	LLFacebookConnect::instance().checkConnectionToFacebook(true);
-
-	//Clear only the facebook browser cookies so that the facebook login screen appears
-	LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); 
-}
-
-void LLSocialAccountPanel::onDisconnect()
-{
-	LLFacebookConnect::instance().disconnectFromFacebook();
-
-	LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); 
-}
-
-////////////////////////
-//LLFloaterSocial///////
-////////////////////////
-
-LLFloaterSocial::LLFloaterSocial(const LLSD& key) : LLFloater(key),
-    mSocialPhotoPanel(NULL),
-    mStatusErrorText(NULL),
-    mStatusLoadingText(NULL),
-    mStatusLoadingIndicator(NULL)
-{
-	mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterSocial::onCancel, this));
-}
-
-void LLFloaterSocial::onCancel()
-{
-    closeFloater();
-}
-
-BOOL LLFloaterSocial::postBuild()
-{
-    // Keep tab of the Photo Panel
-	mSocialPhotoPanel = static_cast<LLSocialPhotoPanel*>(getChild<LLUICtrl>("panel_social_photo"));
-    // Connection status widgets
-    mStatusErrorText = getChild<LLTextBox>("connection_error_text");
-    mStatusLoadingText = getChild<LLTextBox>("connection_loading_text");
-    mStatusLoadingIndicator = getChild<LLUICtrl>("connection_loading_indicator");
-	return LLFloater::postBuild();
-}
-
-void LLFloaterSocial::showPhotoPanel()
-{
-	LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mSocialPhotoPanel->getParent());
-	if (!parent)
-	{
-		llwarns << "Cannot find panel container" << llendl;
-		return;
-	}
-
-	parent->selectTabPanel(mSocialPhotoPanel);
-}
-
-// static
-void LLFloaterSocial::preUpdate()
-{
-	LLFloaterSocial* instance = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social");
-	if (instance)
-	{
-		//Will set file size text to 'unknown'
-		instance->mSocialPhotoPanel->updateControls();
-	}
-}
-
-// static
-void LLFloaterSocial::postUpdate()
-{
-	LLFloaterSocial* instance = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social");
-	if (instance)
-	{
-		//Will set the file size text
-		instance->mSocialPhotoPanel->updateControls();
-
-		// The refresh button is initially hidden. We show it after the first update,
-		// i.e. after snapshot is taken
-		LLUICtrl * refresh_button = instance->mSocialPhotoPanel->getRefreshBtn();
-
-		if (!refresh_button->getVisible())
-		{
-			refresh_button->setVisible(true);
-		}
-		
-	}
-}
-
-void LLFloaterSocial::draw()
-{
-    if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator)
-    {
-        mStatusErrorText->setVisible(false);
-        mStatusLoadingText->setVisible(false);
-        mStatusLoadingIndicator->setVisible(false);
-        LLFacebookConnect::EConnectionState connection_state = LLFacebookConnect::instance().getConnectionState();
-        std::string status_text;
-        
-        switch (connection_state)
-        {
-        case LLFacebookConnect::FB_NOT_CONNECTED:
-            // No status displayed when first opening the panel and no connection done
-        case LLFacebookConnect::FB_CONNECTED:
-            // When successfully connected, no message is displayed
-        case LLFacebookConnect::FB_POSTED:
-            // No success message to show since we actually close the floater after successful posting completion
-            break;
-        case LLFacebookConnect::FB_CONNECTION_IN_PROGRESS:
-            // Connection loading indicator
-            mStatusLoadingText->setVisible(true);
-            status_text = LLTrans::getString("SocialFacebookConnecting");
-            mStatusLoadingText->setValue(status_text);
-            mStatusLoadingIndicator->setVisible(true);
-            break;
-        case LLFacebookConnect::FB_POSTING:
-            // Posting indicator
-            mStatusLoadingText->setVisible(true);
-            status_text = LLTrans::getString("SocialFacebookPosting");
-            mStatusLoadingText->setValue(status_text);
-            mStatusLoadingIndicator->setVisible(true);
-			break;
-        case LLFacebookConnect::FB_CONNECTION_FAILED:
-            // Error connecting to the service
-            mStatusErrorText->setVisible(true);
-            status_text = LLTrans::getString("SocialFacebookErrorConnecting");
-            mStatusErrorText->setValue(status_text);
-            break;
-        case LLFacebookConnect::FB_POST_FAILED:
-            // Error posting to the service
-            mStatusErrorText->setVisible(true);
-            status_text = LLTrans::getString("SocialFacebookErrorPosting");
-            mStatusErrorText->setValue(status_text);
-            break;
-		case LLFacebookConnect::FB_DISCONNECTING:
-			// Disconnecting loading indicator
-			mStatusLoadingText->setVisible(true);
-			status_text = LLTrans::getString("SocialFacebookDisconnecting");
-			mStatusLoadingText->setValue(status_text);
-			mStatusLoadingIndicator->setVisible(true);
-			break;
-		case LLFacebookConnect::FB_DISCONNECT_FAILED:
-			// Error disconnecting from the service
-			mStatusErrorText->setVisible(true);
-			status_text = LLTrans::getString("SocialFacebookErrorDisconnecting");
-			mStatusErrorText->setValue(status_text);
-			break;
-        }
-    }
-	LLFloater::draw();
-}
-
diff --git a/indra/newview/llfloatersocial.h b/indra/newview/llfloatersocial.h
deleted file mode 100644
index 041ae8a268..0000000000
--- a/indra/newview/llfloatersocial.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/** 
-* @file   llfloatersocial.h
-* @brief  Header file for llfloatersocial
-* @author Gilbert@lindenlab.com
-*
-* $LicenseInfo:firstyear=2013&license=viewerlgpl$
-* Second Life Viewer Source Code
-* Copyright (C) 2013, Linden Research, Inc.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser General Public
-* License as published by the Free Software Foundation;
-* version 2.1 of the License only.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this library; if not, write to the Free Software
-* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*
-* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
-* $/LicenseInfo$
-*/
-#ifndef LL_LLFLOATERSOCIAL_H
-#define LL_LLFLOATERSOCIAL_H
-
-#include "llfloater.h"
-#include "lltextbox.h"
-#include "llviewertexture.h"
-
-class LLIconCtrl;
-class LLCheckBoxCtrl;
-class LLSnapshotLivePreview;
-
-class LLSocialStatusPanel : public LLPanel
-{
-public:
-    LLSocialStatusPanel();
-	BOOL postBuild();
-	void draw();
-    void onSend();
-	bool onFacebookConnectStateChange(const LLSD& data);
-
-	void sendStatus();
-	void clearAndClose();
-
-private:
-	LLUICtrl* mMessageTextEditor;
-	LLUICtrl* mPostButton;
-	LLUICtrl* mCancelButton;
-};
-
-class LLSocialPhotoPanel : public LLPanel
-{
-public:
-	LLSocialPhotoPanel();
-	~LLSocialPhotoPanel();
-
-	BOOL postBuild();
-	void draw();
-
-	LLSnapshotLivePreview* getPreviewView();
-	void onVisibilityChange(const LLSD& new_visibility);
-	void onClickNewSnapshot();
-	void onSend();
-	bool onFacebookConnectStateChange(const LLSD& data);
-
-	void sendPhoto();
-	void clearAndClose();
-
-	void updateControls();
-	void updateResolution(BOOL do_update);
-	void checkAspectRatio(S32 index);
-	LLUICtrl* getRefreshBtn();
-
-private:
-	LLHandle<LLView> mPreviewHandle;
-
-	LLUICtrl * mSnapshotPanel;
-	LLUICtrl * mResolutionComboBox;
-	LLUICtrl * mRefreshBtn;
-	LLUICtrl * mWorkingLabel;
-	LLUICtrl * mThumbnailPlaceholder;
-	LLUICtrl * mCaptionTextBox;
-	LLUICtrl * mLocationCheckbox;
-	LLUICtrl * mPostButton;
-	LLUICtrl* mCancelButton;
-};
-
-class LLSocialCheckinPanel : public LLPanel
-{
-public:
-    LLSocialCheckinPanel();
-	BOOL postBuild();
-	void draw();
-    void onSend();
-	bool onFacebookConnectStateChange(const LLSD& data);
-
-	void sendCheckin();
-	void clearAndClose();
-
-private:
-    std::string mMapUrl;
-    LLPointer<LLViewerFetchedTexture> mMapTexture;
-	LLUICtrl* mPostButton;
-	LLUICtrl* mCancelButton;
-	LLUICtrl* mMessageTextEditor;
-    LLUICtrl* mMapLoadingIndicator;
-    LLIconCtrl* mMapPlaceholder;
-    LLIconCtrl* mMapDefault;
-    LLCheckBoxCtrl* mMapCheckBox;
-    bool mReloadingMapTexture;
-};
-
-class LLSocialAccountPanel : public LLPanel
-{
-public:
-	LLSocialAccountPanel();
-	BOOL postBuild();
-	void draw();
-
-private:
-	void onVisibilityChange(const LLSD& new_visibility);
-	bool onFacebookConnectStateChange(const LLSD& data);
-	bool onFacebookConnectInfoChange();
-	void onConnect();
-	void onUseAnotherAccount();
-	void onDisconnect();
-
-	void showConnectButton();
-	void hideConnectButton();
-	void showDisconnectedLayout();
-	void showConnectedLayout();
-
-	LLTextBox * mAccountCaptionLabel;
-	LLTextBox * mAccountNameLabel;
-	LLUICtrl * mPanelButtons;
-	LLUICtrl * mConnectButton;
-	LLUICtrl * mDisconnectButton;
-};
-
-
-class LLFloaterSocial : public LLFloater
-{
-public:
-	LLFloaterSocial(const LLSD& key);
-	BOOL postBuild();
-	void draw();
-	void onCancel();
-	
-	void showPhotoPanel();
-
-	static void preUpdate();
-	static void postUpdate();
-
-private:
-	LLSocialPhotoPanel* mSocialPhotoPanel;
-    LLTextBox* mStatusErrorText;
-    LLTextBox* mStatusLoadingText;
-    LLUICtrl*  mStatusLoadingIndicator;
-};
-
-#endif // LL_LLFLOATERSOCIAL_H
-
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index 82ed066b1a..18a1fcbba9 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -622,7 +622,7 @@ void LLTwitterAccountPanel::onDisconnect()
 ////////////////////////
 
 LLFloaterTwitter::LLFloaterTwitter(const LLSD& key) : LLFloater(key),
-    mSocialPhotoPanel(NULL),
+    mTwitterPhotoPanel(NULL),
     mStatusErrorText(NULL),
     mStatusLoadingText(NULL),
     mStatusLoadingIndicator(NULL)
@@ -638,7 +638,7 @@ void LLFloaterTwitter::onCancel()
 BOOL LLFloaterTwitter::postBuild()
 {
     // Keep tab of the Photo Panel
-	mSocialPhotoPanel = static_cast<LLTwitterPhotoPanel*>(getChild<LLUICtrl>("panel_twitter_photo"));
+	mTwitterPhotoPanel = static_cast<LLTwitterPhotoPanel*>(getChild<LLUICtrl>("panel_twitter_photo"));
     // Connection status widgets
     mStatusErrorText = getChild<LLTextBox>("connection_error_text");
     mStatusLoadingText = getChild<LLTextBox>("connection_loading_text");
@@ -648,14 +648,14 @@ BOOL LLFloaterTwitter::postBuild()
 
 void LLFloaterTwitter::showPhotoPanel()
 {
-	LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mSocialPhotoPanel->getParent());
+	LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mTwitterPhotoPanel->getParent());
 	if (!parent)
 	{
 		llwarns << "Cannot find panel container" << llendl;
 		return;
 	}
 
-	parent->selectTabPanel(mSocialPhotoPanel);
+	parent->selectTabPanel(mTwitterPhotoPanel);
 }
 
 // static
@@ -665,7 +665,7 @@ void LLFloaterTwitter::preUpdate()
 	if (instance)
 	{
 		//Will set file size text to 'unknown'
-		instance->mSocialPhotoPanel->updateControls();
+		instance->mTwitterPhotoPanel->updateControls();
 	}
 }
 
@@ -676,11 +676,11 @@ void LLFloaterTwitter::postUpdate()
 	if (instance)
 	{
 		//Will set the file size text
-		instance->mSocialPhotoPanel->updateControls();
+		instance->mTwitterPhotoPanel->updateControls();
 
 		// The refresh button is initially hidden. We show it after the first update,
 		// i.e. after snapshot is taken
-		LLUICtrl * refresh_button = instance->mSocialPhotoPanel->getRefreshBtn();
+		LLUICtrl * refresh_button = instance->mTwitterPhotoPanel->getRefreshBtn();
 
 		if (!refresh_button->getVisible())
 		{
diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h
index 5305143552..f267f76694 100644
--- a/indra/newview/llfloatertwitter.h
+++ b/indra/newview/llfloatertwitter.h
@@ -121,7 +121,7 @@ public:
 	static void postUpdate();
 
 private:
-	LLTwitterPhotoPanel* mSocialPhotoPanel;
+	LLTwitterPhotoPanel* mTwitterPhotoPanel;
     LLTextBox* mStatusErrorText;
     LLTextBox* mStatusLoadingText;
     LLUICtrl*  mStatusLoadingIndicator;
diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp
index 4cadd837d1..a7b9b6d22e 100755
--- a/indra/newview/llpanelsnapshotoptions.cpp
+++ b/indra/newview/llpanelsnapshotoptions.cpp
@@ -32,7 +32,7 @@
 
 #include "llfloatersnapshot.h" // FIXME: create a snapshot model
 #include "llfloaterreg.h"
-#include "llfloatersocial.h"
+#include "llfloaterfacebook.h"
 #include "llfloaterflickr.h"
 #include "llfloatertwitter.h"
 
@@ -144,12 +144,12 @@ void LLPanelSnapshotOptions::onSendToFacebook()
 {
 	LLFloaterReg::hideInstance("snapshot");
 
-	LLFloaterSocial* social_floater = dynamic_cast<LLFloaterSocial*>(LLFloaterReg::getInstance("social"));
-	if (social_floater)
+	LLFloaterFacebook* facebook_floater = dynamic_cast<LLFloaterFacebook*>(LLFloaterReg::getInstance("facebook"));
+	if (facebook_floater)
 	{
-		social_floater->showPhotoPanel();
+		facebook_floater->showPhotoPanel();
 	}
-	LLFloaterReg::showInstance("social");
+	LLFloaterReg::showInstance("facebook");
 }
 
 void LLPanelSnapshotOptions::onSendToTwitter()
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 67952f83c7..9feeea1644 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -34,7 +34,7 @@
 #include "lleconomy.h"
 #include "llfloaterperms.h"
 #include "llfloaterreg.h"
-#include "llfloatersocial.h"
+#include "llfloaterfacebook.h"
 #include "llfloaterflickr.h"
 #include "llfloatertwitter.h"
 #include "llimagebmp.h"
@@ -210,7 +210,7 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail
 		mSnapshotDelayTimer.start();
 		mSnapshotDelayTimer.setTimerExpirySec(delay);
 		LLFloaterSnapshot::preUpdate();
-		LLFloaterSocial::preUpdate();
+		LLFloaterFacebook::preUpdate();
 		LLFloaterFlickr::preUpdate();
 		LLFloaterTwitter::preUpdate();
 	}
@@ -769,7 +769,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 	}
 	lldebugs << "done creating snapshot" << llendl;
 	LLFloaterSnapshot::postUpdate();
-	LLFloaterSocial::postUpdate();
+	LLFloaterFacebook::postUpdate();
 	LLFloaterFlickr::postUpdate();
 	LLFloaterTwitter::postUpdate();
 
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 1e07aaf5ec..e38ffbbc63 100755
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -60,6 +60,7 @@
 #include "llfloatereditwater.h"
 #include "llfloaterenvironmentsettings.h"
 #include "llfloaterevent.h"
+#include "llfloaterfacebook.h"
 #include "llfloaterflickr.h"
 #include "llfloaterfonttest.h"
 #include "llfloatergesture.h"
@@ -104,7 +105,6 @@
 #include "llfloatersettingsdebug.h"
 #include "llfloatersidepanelcontainer.h"
 #include "llfloatersnapshot.h"
-#include "llfloatersocial.h"
 #include "llfloatersounddevices.h"
 #include "llfloaterspellchecksettings.h"
 #include "llfloatertelehub.h"
@@ -306,9 +306,6 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterReg::add("sell_land", "floater_sell_land.xml", &LLFloaterSellLand::buildFloater);
 	LLFloaterReg::add("settings_debug", "floater_settings_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSettingsDebug>);
 	LLFloaterReg::add("sound_devices", "floater_sound_devices.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundDevices>);
-	LLFloaterReg::add("social", "floater_social.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSocial>);
-	LLFloaterReg::add("flickr", "floater_flickr.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFlickr>);
-	LLFloaterReg::add("twitter", "floater_twitter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTwitter>);
 	LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>);
 	LLFloaterReg::add("start_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRunQueue>);
 	LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>);
@@ -317,10 +314,15 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterReg::add("my_profile", "floater_my_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
 	LLFloaterReg::add("profile", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
 	LLFloaterReg::add("how_to", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
+
 	LLFloaterReg::add("fbc_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
 	LLFloaterReg::add("flickr_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
 	LLFloaterReg::add("twitter_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
 	
+	LLFloaterReg::add("facebook", "floater_facebook.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFacebook>);
+	LLFloaterReg::add("flickr", "floater_flickr.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFlickr>);
+	LLFloaterReg::add("twitter", "floater_twitter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTwitter>);
+	
 	LLFloaterUIPreviewUtil::registerFloater();
 	LLFloaterReg::add("upload_anim_bvh", "floater_animation_bvh_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBvhPreview>, "upload");
 	LLFloaterReg::add("upload_anim_anim", "floater_animation_anim_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAnimPreview>, "upload");
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index e42743824e..751558fc93 100755
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -133,6 +133,8 @@ with the same filename but different name
   <texture name="Command_Chat_Icon"         file_name="toolbar_icons/chat.png"         preload="true" />
   <texture name="Command_Compass_Icon"      file_name="toolbar_icons/land.png"         preload="true" />
   <texture name="Command_Destinations_Icon" file_name="toolbar_icons/destinations.png" preload="true" />
+  <texture name="Command_Facebook_Icon"     file_name="toolbar_icons/facebook.png"     preload="true" />
+  <texture name="Command_Flickr_Icon"       file_name="toolbar_icons/flickr.png"       preload="true" />
   <texture name="Command_Gestures_Icon"     file_name="toolbar_icons/gestures.png"     preload="true" />
   <texture name="Command_HowTo_Icon"        file_name="toolbar_icons/howto.png"        preload="true" />
   <texture name="Command_Inventory_Icon"    file_name="toolbar_icons/inventory.png"    preload="true" />
@@ -148,11 +150,9 @@ with the same filename but different name
   <texture name="Command_Preferences_Icon"  file_name="toolbar_icons/preferences.png"  preload="true" />
   <texture name="Command_Profile_Icon"      file_name="toolbar_icons/profile.png"      preload="true" />
   <texture name="Command_Search_Icon"       file_name="toolbar_icons/search.png"       preload="true" />
-  <texture name="Command_Social_Icon"       file_name="toolbar_icons/facebook.png"     preload="true" />
-  <texture name="Command_Flickr_Icon"       file_name="toolbar_icons/flickr.png"     preload="true" />
-  <texture name="Command_Twitter_Icon"      file_name="toolbar_icons/twitter.png"     preload="true" />
   <texture name="Command_Snapshot_Icon"     file_name="toolbar_icons/snapshot.png"     preload="true" />
   <texture name="Command_Speak_Icon"        file_name="toolbar_icons/speak.png"        preload="true" />
+  <texture name="Command_Twitter_Icon"      file_name="toolbar_icons/twitter.png"      preload="true" />
   <texture name="Command_View_Icon"         file_name="toolbar_icons/view.png"         preload="true" />
   <texture name="Command_Voice_Icon"        file_name="toolbar_icons/nearbyvoice.png"  preload="true" />
   <texture name="Caret_Bottom_Icon"         file_name="toolbar_icons/caret_bottom.png" preload="true" scale.left="1" scale.top="23" scale.right="15" scale.bottom="1" />
diff --git a/indra/newview/skins/default/xui/en/floater_facebook.xml b/indra/newview/skins/default/xui/en/floater_facebook.xml
new file mode 100644
index 0000000000..820e105e53
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_facebook.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<floater
+  positioning="cascading"
+  can_close="true"
+  can_resize="false"
+  help_topic="floater_facebook"
+  layout="topleft"
+  name="floater_facebook"
+  save_rect="true"
+  single_instance="true"
+  reuse_instance="true"
+  title="POST TO FACEBOOK"
+  height="482"
+  width="304">
+  <panel
+   height="482"
+   width="304"
+   visible="true"
+   name="background"
+   follows="all"
+   top="0"
+   left="0">
+   <tab_container
+     name="tabs"
+     tab_group="1"
+     tab_min_width="70"
+     tab_height="30"
+     tab_position="top"
+     top="7"
+     height="437"
+     halign="center">
+     <panel
+       filename="panel_facebook_status.xml"
+       class="llfacebookstatuspanel"
+       follows="all"
+       label="STATUS"
+       name="panel_facebook_status"/>
+     <panel
+       filename="panel_facebook_photo.xml"
+       class="llfacebookphotopanel"
+       follows="all"
+       label="PHOTO"
+       name="panel_facebook_photo"/>
+     <panel
+       filename="panel_facebook_place.xml"
+       class="llfacebookcheckinpanel"
+       follows="all"
+       label="CHECK IN"
+       name="panel_facebook_place"/>
+     <panel
+       filename="panel_facebook_account.xml"
+       class="llfacebookaccountpanel"
+       follows="all"
+       label="ACCOUNT"
+       name="panel_facebook_account"/>     
+    </tab_container>
+    <panel
+     name="connection_status_panel"
+     follows="left|bottom|right"
+     height="24">
+     <text
+      name="connection_error_text"
+      type="string"
+      follows="left|bottom|right"
+      top="5"
+      left="9"
+      width="250"
+      height="20"
+      wrap="true"
+      halign="left"
+      valign="center"
+      text_color="DrYellow"
+      font="SansSerif">
+      Error
+     </text>
+     <loading_indicator
+      follows="left|bottom|right"
+      height="24"
+      width="24"
+      name="connection_loading_indicator"
+      top="2"
+      left="9"
+      visible="true"/>
+     <text
+      name="connection_loading_text"
+      type="string"
+      follows="left|bottom|right"
+      top="5"
+      left_pad="5"
+      width="250"
+      height="20"
+      wrap="true"
+      halign="left"
+      valign="center"
+      text_color="EmphasisColor"
+      font="SansSerif">
+      Loading...
+    </text>
+  </panel>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_social.xml b/indra/newview/skins/default/xui/en/floater_social.xml
deleted file mode 100644
index b7ff374d5f..0000000000
--- a/indra/newview/skins/default/xui/en/floater_social.xml
+++ /dev/null
@@ -1,101 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
-<floater
-  positioning="cascading"
-  can_close="true"
-  can_resize="false"
-  help_topic="floater_social"
-  layout="topleft"
-  name="floater_social"
-  save_rect="true"
-  single_instance="true"
-  reuse_instance="true"
-  title="POST TO FACEBOOK"
-  height="482"
-  width="304">
-  <panel
-   height="482"
-   width="304"
-   visible="true"
-   name="background"
-   follows="all"
-   top="0"
-   left="0">
-   <tab_container
-     name="tabs"
-     tab_group="1"
-     tab_min_width="70"
-     tab_height="30"
-     tab_position="top"
-     top="7"
-     height="437"
-     halign="center">
-     <panel
-       filename="panel_social_status.xml"
-       class="llsocialstatuspanel"
-       follows="all"
-       label="STATUS"
-       name="panel_social_status"/>
-     <panel
-       filename="panel_social_photo.xml"
-       class="llsocialphotopanel"
-       follows="all"
-       label="PHOTO"
-       name="panel_social_photo"/>
-     <panel
-       filename="panel_social_place.xml"
-       class="llsocialcheckinpanel"
-       follows="all"
-       label="CHECK IN"
-       name="panel_social_place"/>
-     <panel
-       filename="panel_social_account.xml"
-       class="llsocialaccountpanel"
-       follows="all"
-       label="ACCOUNT"
-       name="panel_social_account"/>     
-    </tab_container>
-    <panel
-     name="connection_status_panel"
-     follows="left|bottom|right"
-     height="24">
-     <text
-      name="connection_error_text"
-      type="string"
-      follows="left|bottom|right"
-      top="5"
-      left="9"
-      width="250"
-      height="20"
-      wrap="true"
-      halign="left"
-      valign="center"
-      text_color="DrYellow"
-      font="SansSerif">
-      Error
-     </text>
-     <loading_indicator
-      follows="left|bottom|right"
-      height="24"
-      width="24"
-      name="connection_loading_indicator"
-      top="2"
-      left="9"
-      visible="true"/>
-     <text
-      name="connection_loading_text"
-      type="string"
-      follows="left|bottom|right"
-      top="5"
-      left_pad="5"
-      width="250"
-      height="20"
-      wrap="true"
-      halign="left"
-      valign="center"
-      text_color="EmphasisColor"
-      font="SansSerif">
-      Loading...
-    </text>
-  </panel>
- </panel>
-</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 79adb4e8bb..905988e09d 100755
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -285,7 +285,7 @@
         name="Facebook">
         <menu_item_call.on_click
           function="Floater.Toggle"
-          parameter="social"/>
+          parameter="facebook"/>
       </menu_item_call>
       <menu_item_call
         label="Twitter..."
diff --git a/indra/newview/skins/default/xui/en/panel_facebook_account.xml b/indra/newview/skins/default/xui/en/panel_facebook_account.xml
new file mode 100644
index 0000000000..f091d2e9b9
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_facebook_account.xml
@@ -0,0 +1,75 @@
+<panel
+	 height="400"
+	 width="304"
+	 layout="topleft"
+   name="panel_facebook_account">
+  <string
+      name="facebook_connected"
+      value="You are connected to Facebook as:" />
+  <string
+      name="facebook_disconnected"
+      value="Not connected to Facebook" />
+  <text
+   layout="topleft"
+   length="1"
+   follows="top|left"
+   font="SansSerif"
+   height="16"
+   left="9"
+   name="account_caption_label"
+   top="21"
+   type="string">
+    Not connected to Facebook.
+  </text>
+  <text
+   layout="topleft"
+   top_pad="2"
+   length="1"
+   follows="top|left"
+   font="SansSerif"
+   height="16"
+   left="9"
+   name="account_name_label"
+   parse_urls="true"
+   type="string"/>
+  <panel
+    layout="topleft"
+    name="panel_buttons"
+    height="345"
+    left="9">
+    <button
+     layout="topleft"
+     follows="left|top"
+     top_pad="9"
+     visible="true"
+     height="23"
+     label="Connect..."
+     name="connect_btn"
+     width="210">
+      <commit_callback function="SocialSharing.Connect"/>
+    </button>
+
+    <button
+     layout="topleft"
+     follows="left|top"
+     top_delta="0"
+     height="23"
+     label="Disconnect"
+     name="disconnect_btn"
+     width="210"
+     visible="false">
+      <commit_callback function="SocialSharing.Disconnect"/>
+    </button>
+    <text
+      layout="topleft"
+      length="1"
+      follows="top|left"
+      height="16"
+      left="0"
+      name="account_learn_more_label"
+      top_pad="20"
+      type="string">
+      [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share/ta-p/2149711 Learn about posting to Facebook]
+    </text>
+  </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
new file mode 100644
index 0000000000..19f9f2fb74
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
@@ -0,0 +1,152 @@
+    <panel
+      height="400"
+      width="304"
+      layout="topleft"
+      name="panel_facebook_photo">
+      <layout_stack
+	   layout="topleft"
+       border_size="0"
+       height="392"
+       follows="all"
+       orientation="vertical"
+       name="stack_photo"
+       top="8">
+        <layout_panel	
+         name="snapshot_panel"
+         height="367">
+            <combo_box
+             control_name="SocialPhotoResolution"
+             follows="left|top"
+             top="6"
+             left="9"
+             name="resolution_combobox"
+             tool_tip="Image resolution"
+             height="21"
+             width="135">
+              <combo_box.item
+               label="Current Window"
+               name="CurrentWindow"
+               value="[i0,i0]" />
+              <combo_box.item
+               label="640x480"
+               name="640x480"
+               value="[i640,i480]" />
+              <combo_box.item
+               label="800x600"
+               name="800x600"
+               value="[i800,i600]" />
+              <combo_box.item
+               label="1024x768"
+               name="1024x768"
+               value="[i1024,i768]" />
+            </combo_box>
+            <text
+             follows="left|top"
+             font="SansSerifSmall"
+             height="14"
+             left="208"
+             length="1"
+             halign="right"
+             name="file_size_label"
+             top="9"
+             type="string"
+             width="50">
+              [SIZE] KB
+            </text>
+            <panel
+                height="150"
+                width="250"
+                visible="true"
+                name="thumbnail_placeholder"
+                top="33"
+                follows="left|top"
+                left="9">
+            </panel>
+            <button
+             follows="left|top"
+             height="23"
+             label="Refresh"
+             left="9"
+             top_pad="5"
+             name="new_snapshot_btn"
+             tool_tip="Click to refresh"
+             visible="true"
+             width="100" >
+             <button.commit_callback
+               function="SocialSharing.RefreshPhoto" />
+            </button>
+            <text
+                follows="left|top"
+                font="SansSerif"
+                text_color="EmphasisColor"
+                height="14"
+                top_pad="-19"
+                left_pad="-20"
+                length="1"
+                halign="center"
+                name="working_lbl"
+                translate="false"
+                type="string"
+                visible="true"
+                width="150">
+                Refreshing...
+            </text>
+            <text
+             length="1"
+             follows="top|left|right"
+             font="SansSerif"
+             height="16"
+             left="9"
+             name="caption_label"
+             top_pad="20"
+             type="string">
+              Comment (optional):
+            </text>
+            <text_editor
+             follows="left|top"
+             height="87"
+             width="250"
+             left="9"
+             length="1"
+             max_length="700"
+             name="photo_caption"
+             type="string"
+             word_wrap="true">
+            </text_editor>
+            <check_box
+             follows="left|top"
+             initial_value="true"
+             label="Include location in posting"
+             name="add_location_cb"
+              left="9"
+              height="16"
+             top_pad="8"/>
+        </layout_panel>
+        <layout_panel
+          name="photo_button_panel"
+          height="25">
+          <button
+           follows="left|top"
+           top="0"
+           left="9"
+           height="23"
+           label="Post"
+           name="post_photo_btn"
+           width="100">
+            <button.commit_callback
+             function="SocialSharing.SendPhoto" />
+          </button>
+          <button
+               follows="left|top"
+               height="23"
+               label="Cancel"
+               name="cancel_photo_btn"
+               left_pad="15"
+               top_delta="0"
+               width="100">
+            <button.commit_callback
+             function="SocialSharing.Cancel" />
+          </button>          
+        </layout_panel>        
+      </layout_stack>
+    </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_facebook_place.xml b/indra/newview/skins/default/xui/en/panel_facebook_place.xml
new file mode 100644
index 0000000000..1eea8f317b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_facebook_place.xml
@@ -0,0 +1,132 @@
+    <panel
+      height="400"
+      width="304"
+	  layout="topleft"
+      name="panel_facebook_place">
+      <layout_stack
+	    layout="topleft"
+        border_size="0"
+        height="392"
+        follows="all"
+        orientation="vertical"
+        name="stack_place"
+        top="8">
+        <layout_panel
+          name="place_detail_panel"
+          height="181">
+          <text
+            length="1"
+            follows="top|left|right"
+            font="SansSerif"
+            height="16"
+            left="9"
+            name="place_caption_label"
+            top="13"
+            type="string">
+            Say something about where you are:
+          </text>
+          <text_editor
+            follows="top|left"
+            height="150"
+            width="250"
+            left="9"
+            length="1"
+            max_length="700"
+            name="place_caption"
+            type="string"
+            word_wrap="true">
+           </text_editor>
+          </layout_panel>
+          <layout_panel
+            name="place_map_panel"
+            height="186">
+              <panel
+                  follows="left|top"
+                  height="128"
+                  width="128"
+                  background_visible="true"
+                  bg_opaque_color="Black"
+                  bg_alpha_color="Black"
+                  top="20"
+                  left="9"
+                  visible="true"
+                  name="map_border">
+              </panel>
+              <loading_indicator
+              follows="left|top"
+              height="24"
+              width="24"
+              name="map_loading_indicator"
+              top="77"
+              left="61"
+              visible="true"/>
+              <icon
+                follows="left|top"
+                height="128"
+                width="128"
+                image_name="Map_Placeholder_Icon"
+                layout="topleft"
+                top="20"
+                left="9"
+                visible="true"
+                name="map_placeholder">
+              </icon>
+              <icon
+                  follows="left|top"
+                  height="128"
+                  width="128"
+                  image_name="Map_Placeholder_Icon"
+                  layout="topleft"
+                  top="20"
+                  left="9"
+                  visible="true"
+                  name="map_default">
+              </icon>
+            <check_box
+              follows="left|top"
+              initial_value="false"
+              top_delta="8"
+              width="8"
+              label=""
+              name="add_place_view_cb"
+              left_pad="5"/>
+            <text
+              follows="left|top"
+              font="SansSerif"
+              height="32"
+              width="130"
+              word_wrap="true"
+              left_pad="12"
+              top_delta="-8"
+              type="string">
+              Include overhead view of location
+            </text>
+          </layout_panel>
+          <layout_panel
+            name="place_button_panel"
+            height="25">
+            <button
+              follows="left|top"
+              top="0"
+              left="9"
+              height="23"
+              label="Post"
+              name="post_place_btn"
+              width="100">
+              <button.commit_callback
+                 function="SocialSharing.SendCheckin" />
+            </button>
+            <button
+              follows="left|top"
+              height="23"
+              label="Cancel"
+              name="cancel_place_btn"
+              left_pad="15"
+              top_delta="0"
+              width="100">
+              <button.commit_callback
+                  function="SocialSharing.Cancel" />
+            </button>
+        </layout_panel>
+     </layout_stack>
+    </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_facebook_status.xml b/indra/newview/skins/default/xui/en/panel_facebook_status.xml
new file mode 100644
index 0000000000..50e15c2e80
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_facebook_status.xml
@@ -0,0 +1,67 @@
+    <panel
+	 height="400"
+	 width="304"
+	 layout="topleft"
+     name="panel_facebook_status">
+     <layout_stack
+      layout="topleft"
+      border_size="0"
+      height="392"
+      follows="all"
+      orientation="vertical"
+      name="stack_status"
+      top="8">
+      <layout_panel
+       name="status_detail_panel"
+       height="367">
+       <text
+        length="1"
+        follows="top|left|right"
+        font="SansSerif"
+        height="16"
+        left="9"
+        name="status_caption_label"
+        top="13"
+        type="string">
+        What's on your mind?
+       </text>
+       <text_editor
+        follows="left|top"
+        height="150"
+        width="250"
+        left="9"
+        length="1"
+        max_length="700"
+        name="status_message"
+        type="string"
+        word_wrap="true">
+       </text_editor>
+      </layout_panel>
+      <layout_panel
+       name="status_button_panel"
+       height="25">
+       <button
+        follows="left|top"
+        top="0"
+        left="9"
+        height="23"
+        label="Post"
+        name="post_status_btn"
+        width="100">
+        <button.commit_callback
+          function="SocialSharing.SendStatus" />
+       </button>
+       <button
+        follows="left|top"
+        height="23"
+        label="Cancel"
+        name="cancel_status_btn"
+        left_pad="15"
+        top_delta="0"
+        width="100">
+        <button.commit_callback
+          function="SocialSharing.Cancel" />
+       </button>
+      </layout_panel>
+     </layout_stack>
+    </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_social_account.xml b/indra/newview/skins/default/xui/en/panel_social_account.xml
deleted file mode 100644
index d7235396fe..0000000000
--- a/indra/newview/skins/default/xui/en/panel_social_account.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<panel
-	 height="400"
-	 width="304"
-	 layout="topleft"
-   name="panel_social_account">
-  <string
-      name="facebook_connected"
-      value="You are connected to Facebook as:" />
-  <string
-      name="facebook_disconnected"
-      value="Not connected to Facebook" />
-  <text
-   layout="topleft"
-   length="1"
-   follows="top|left"
-   font="SansSerif"
-   height="16"
-   left="9"
-   name="account_caption_label"
-   top="21"
-   type="string">
-    Not connected to Facebook.
-  </text>
-  <text
-   layout="topleft"
-   top_pad="2"
-   length="1"
-   follows="top|left"
-   font="SansSerif"
-   height="16"
-   left="9"
-   name="account_name_label"
-   parse_urls="true"
-   type="string"/>
-  <panel
-    layout="topleft"
-    name="panel_buttons"
-    height="345"
-    left="9">
-    <button
-     layout="topleft"
-     follows="left|top"
-     top_pad="9"
-     visible="true"
-     height="23"
-     label="Connect..."
-     name="connect_btn"
-     width="210">
-      <commit_callback function="SocialSharing.Connect"/>
-    </button>
-
-    <button
-     layout="topleft"
-     follows="left|top"
-     top_delta="0"
-     height="23"
-     label="Disconnect"
-     name="disconnect_btn"
-     width="210"
-     visible="false">
-      <commit_callback function="SocialSharing.Disconnect"/>
-    </button>
-    <text
-      layout="topleft"
-      length="1"
-      follows="top|left"
-      height="16"
-      left="0"
-      name="account_learn_more_label"
-      top_pad="20"
-      type="string">
-      [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share/ta-p/2149711 Learn about posting to Facebook]
-    </text>
-  </panel>
-</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_social_photo.xml b/indra/newview/skins/default/xui/en/panel_social_photo.xml
deleted file mode 100644
index a55613b52a..0000000000
--- a/indra/newview/skins/default/xui/en/panel_social_photo.xml
+++ /dev/null
@@ -1,152 +0,0 @@
-    <panel
-      height="400"
-      width="304"
-      layout="topleft"
-      name="panel_social_photo">
-      <layout_stack
-	   layout="topleft"
-       border_size="0"
-       height="392"
-       follows="all"
-       orientation="vertical"
-       name="stack_photo"
-       top="8">
-        <layout_panel	
-         name="snapshot_panel"
-         height="367">
-            <combo_box
-             control_name="SocialPhotoResolution"
-             follows="left|top"
-             top="6"
-             left="9"
-             name="resolution_combobox"
-             tool_tip="Image resolution"
-             height="21"
-             width="135">
-              <combo_box.item
-               label="Current Window"
-               name="CurrentWindow"
-               value="[i0,i0]" />
-              <combo_box.item
-               label="640x480"
-               name="640x480"
-               value="[i640,i480]" />
-              <combo_box.item
-               label="800x600"
-               name="800x600"
-               value="[i800,i600]" />
-              <combo_box.item
-               label="1024x768"
-               name="1024x768"
-               value="[i1024,i768]" />
-            </combo_box>
-            <text
-             follows="left|top"
-             font="SansSerifSmall"
-             height="14"
-             left="208"
-             length="1"
-             halign="right"
-             name="file_size_label"
-             top="9"
-             type="string"
-             width="50">
-              [SIZE] KB
-            </text>
-            <panel
-                height="150"
-                width="250"
-                visible="true"
-                name="thumbnail_placeholder"
-                top="33"
-                follows="left|top"
-                left="9">
-            </panel>
-            <button
-             follows="left|top"
-             height="23"
-             label="Refresh"
-             left="9"
-             top_pad="5"
-             name="new_snapshot_btn"
-             tool_tip="Click to refresh"
-             visible="true"
-             width="100" >
-             <button.commit_callback
-               function="SocialSharing.RefreshPhoto" />
-            </button>
-            <text
-                follows="left|top"
-                font="SansSerif"
-                text_color="EmphasisColor"
-                height="14"
-                top_pad="-19"
-                left_pad="-20"
-                length="1"
-                halign="center"
-                name="working_lbl"
-                translate="false"
-                type="string"
-                visible="true"
-                width="150">
-                Refreshing...
-            </text>
-            <text
-             length="1"
-             follows="top|left|right"
-             font="SansSerif"
-             height="16"
-             left="9"
-             name="caption_label"
-             top_pad="20"
-             type="string">
-              Comment (optional):
-            </text>
-            <text_editor
-             follows="left|top"
-             height="87"
-             width="250"
-             left="9"
-             length="1"
-             max_length="700"
-             name="photo_caption"
-             type="string"
-             word_wrap="true">
-            </text_editor>
-            <check_box
-             follows="left|top"
-             initial_value="true"
-             label="Include location in posting"
-             name="add_location_cb"
-              left="9"
-              height="16"
-             top_pad="8"/>
-        </layout_panel>
-        <layout_panel
-          name="photo_button_panel"
-          height="25">
-          <button
-           follows="left|top"
-           top="0"
-           left="9"
-           height="23"
-           label="Post"
-           name="post_photo_btn"
-           width="100">
-            <button.commit_callback
-             function="SocialSharing.SendPhoto" />
-          </button>
-          <button
-               follows="left|top"
-               height="23"
-               label="Cancel"
-               name="cancel_photo_btn"
-               left_pad="15"
-               top_delta="0"
-               width="100">
-            <button.commit_callback
-             function="SocialSharing.Cancel" />
-          </button>          
-        </layout_panel>        
-      </layout_stack>
-    </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_social_place.xml b/indra/newview/skins/default/xui/en/panel_social_place.xml
deleted file mode 100644
index 13e94f6998..0000000000
--- a/indra/newview/skins/default/xui/en/panel_social_place.xml
+++ /dev/null
@@ -1,132 +0,0 @@
-    <panel
-      height="400"
-      width="304"
-	  layout="topleft"
-      name="panel_social_place">
-      <layout_stack
-	    layout="topleft"
-        border_size="0"
-        height="392"
-        follows="all"
-        orientation="vertical"
-        name="stack_place"
-        top="8">
-        <layout_panel
-          name="place_detail_panel"
-          height="181">
-          <text
-            length="1"
-            follows="top|left|right"
-            font="SansSerif"
-            height="16"
-            left="9"
-            name="place_caption_label"
-            top="13"
-            type="string">
-            Say something about where you are:
-          </text>
-          <text_editor
-            follows="top|left"
-            height="150"
-            width="250"
-            left="9"
-            length="1"
-            max_length="700"
-            name="place_caption"
-            type="string"
-            word_wrap="true">
-           </text_editor>
-          </layout_panel>
-          <layout_panel
-            name="place_map_panel"
-            height="186">
-              <panel
-                  follows="left|top"
-                  height="128"
-                  width="128"
-                  background_visible="true"
-                  bg_opaque_color="Black"
-                  bg_alpha_color="Black"
-                  top="20"
-                  left="9"
-                  visible="true"
-                  name="map_border">
-              </panel>
-              <loading_indicator
-              follows="left|top"
-              height="24"
-              width="24"
-              name="map_loading_indicator"
-              top="77"
-              left="61"
-              visible="true"/>
-              <icon
-                follows="left|top"
-                height="128"
-                width="128"
-                image_name="Map_Placeholder_Icon"
-                layout="topleft"
-                top="20"
-                left="9"
-                visible="true"
-                name="map_placeholder">
-              </icon>
-              <icon
-                  follows="left|top"
-                  height="128"
-                  width="128"
-                  image_name="Map_Placeholder_Icon"
-                  layout="topleft"
-                  top="20"
-                  left="9"
-                  visible="true"
-                  name="map_default">
-              </icon>
-            <check_box
-              follows="left|top"
-              initial_value="false"
-              top_delta="8"
-              width="8"
-              label=""
-              name="add_place_view_cb"
-              left_pad="5"/>
-            <text
-              follows="left|top"
-              font="SansSerif"
-              height="32"
-              width="130"
-              word_wrap="true"
-              left_pad="12"
-              top_delta="-8"
-              type="string">
-              Include overhead view of location
-            </text>
-          </layout_panel>
-          <layout_panel
-            name="place_button_panel"
-            height="25">
-            <button
-              follows="left|top"
-              top="0"
-              left="9"
-              height="23"
-              label="Post"
-              name="post_place_btn"
-              width="100">
-              <button.commit_callback
-                 function="SocialSharing.SendCheckin" />
-            </button>
-            <button
-              follows="left|top"
-              height="23"
-              label="Cancel"
-              name="cancel_place_btn"
-              left_pad="15"
-              top_delta="0"
-              width="100">
-              <button.commit_callback
-                  function="SocialSharing.Cancel" />
-            </button>
-        </layout_panel>
-     </layout_stack>
-    </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_social_status.xml b/indra/newview/skins/default/xui/en/panel_social_status.xml
deleted file mode 100644
index 54cfa3f524..0000000000
--- a/indra/newview/skins/default/xui/en/panel_social_status.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-    <panel
-	 height="400"
-	 width="304"
-	 layout="topleft"
-     name="panel_social_status">
-     <layout_stack
-      layout="topleft"
-      border_size="0"
-      height="392"
-      follows="all"
-      orientation="vertical"
-      name="stack_status"
-      top="8">
-      <layout_panel
-       name="status_detail_panel"
-       height="367">
-       <text
-        length="1"
-        follows="top|left|right"
-        font="SansSerif"
-        height="16"
-        left="9"
-        name="status_caption_label"
-        top="13"
-        type="string">
-        What's on your mind?
-       </text>
-       <text_editor
-        follows="left|top"
-        height="150"
-        width="250"
-        left="9"
-        length="1"
-        max_length="700"
-        name="status_message"
-        type="string"
-        word_wrap="true">
-       </text_editor>
-      </layout_panel>
-      <layout_panel
-       name="status_button_panel"
-       height="25">
-       <button
-        follows="left|top"
-        top="0"
-        left="9"
-        height="23"
-        label="Post"
-        name="post_status_btn"
-        width="100">
-        <button.commit_callback
-          function="SocialSharing.SendStatus" />
-       </button>
-       <button
-        follows="left|top"
-        height="23"
-        label="Cancel"
-        name="cancel_status_btn"
-        left_pad="15"
-        top_delta="0"
-        width="100">
-        <button.commit_callback
-          function="SocialSharing.Cancel" />
-       </button>
-      </layout_panel>
-     </layout_stack>
-    </panel>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index b24cca588e..3806e1287c 100755
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3877,6 +3877,8 @@ Try enclosing path to the editor with double quotes.
   <string name="Command_Conversations_Label">Conversations</string>
   <string name="Command_Compass_Label">Compass</string>
   <string name="Command_Destinations_Label">Destinations</string>
+  <string name="Command_Facebook_Label">Facebook</string>
+  <string name="Command_Flickr_Label">Flickr</string>
   <string name="Command_Gestures_Label">Gestures</string>
   <string name="Command_HowTo_Label">How to</string>
   <string name="Command_Inventory_Label">Inventory</string>
@@ -3892,10 +3894,8 @@ Try enclosing path to the editor with double quotes.
   <string name="Command_Profile_Label">Profile</string>
   <string name="Command_Search_Label">Search</string>
   <string name="Command_Snapshot_Label">Snapshot</string>
-  <string name="Command_Social_Label">Facebook</string>
-  <string name="Command_Flickr_Label">Flickr</string>
-  <string name="Command_Twitter_Label">Twitter</string>
   <string name="Command_Speak_Label">Speak</string>
+  <string name="Command_Twitter_Label">Twitter</string>
   <string name="Command_View_Label">Camera controls</string>
   <string name="Command_Voice_Label">Voice settings</string>
 
@@ -3907,6 +3907,8 @@ Try enclosing path to the editor with double quotes.
   <string name="Command_Conversations_Tooltip">Converse with everyone</string>
   <string name="Command_Compass_Tooltip">Compass</string>
   <string name="Command_Destinations_Tooltip">Destinations of interest</string>
+  <string name="Command_Facebook_Tooltip">Post to Facebook</string>
+  <string name="Command_Flickr_Tooltip">Upload to Flickr</string>
   <string name="Command_Gestures_Tooltip">Gestures for your avatar</string>
   <string name="Command_HowTo_Tooltip">How to do common tasks</string>
   <string name="Command_Inventory_Tooltip">View and use your belongings</string>
@@ -3922,10 +3924,8 @@ Try enclosing path to the editor with double quotes.
   <string name="Command_Profile_Tooltip">Edit or view your profile</string>
   <string name="Command_Search_Tooltip">Find places, events, people</string>
   <string name="Command_Snapshot_Tooltip">Take a picture</string>
-  <string name="Command_Social_Tooltip">Post to Facebook</string>
-  <string name="Command_Flickr_Tooltip">Upload to Flickr</string>
-  <string name="Command_Twitter_Tooltip">Twitter</string>
   <string name="Command_Speak_Tooltip">Speak with people nearby using your microphone</string>
+  <string name="Command_Twitter_Tooltip">Twitter</string>
   <string name="Command_View_Tooltip">Changing camera angle</string>
   <string name="Command_Voice_Tooltip">Volume controls for calls and people near you in world</string>
 
-- 
cgit v1.2.3


From 5a23bf50bcee13a5841f680b13ca480753d367a1 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Thu, 5 Dec 2013 00:29:12 +0000
Subject: Added slshare SLapp support for ACME-1214

---
 indra/newview/llfacebookconnect.cpp | 69 +++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index 0a662b4671..860f488945 100644
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -69,6 +69,75 @@ void toast_user_for_facebook_success()
 
 ///////////////////////////////////////////////////////////////////////////////
 //
+class LLSLShareHandler : public LLCommandHandler
+{
+public:
+	LLSLShareHandler() : LLCommandHandler("slshare", UNTRUSTED_THROTTLE) { }
+    
+	bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
+	{
+		if (tokens.size() >= 1)
+		{
+			if (tokens[0].asString() == "connect")
+			{
+				if (tokens.size() >= 2 && tokens[1].asString() == "flickr")
+				{
+					// this command probably came from the flickr_web browser, so close it
+					LLFloater* flickr_web = LLFloaterReg::getInstance("flickr_web");
+					if (flickr_web)
+					{
+						flickr_web->closeFloater();
+					}
+
+					// connect to flickr
+					if (query_map.has("oauth_token"))
+					{
+						LLFlickrConnect::instance().connectToFlickr(query_map["oauth_token"], query_map.get("oauth_verifier"));
+					}
+					return true;
+				}
+				else if (tokens.size() >= 2 && tokens[1].asString() == "twitter")
+				{
+					// this command probably came from the twitter_web browser, so close it
+					LLFloater* twitter_web = LLFloaterReg::getInstance("twitter_web");
+					if (twitter_web)
+					{
+						twitter_web->closeFloater();
+					}
+
+					// connect to twitter
+					if (query_map.has("oauth_token"))
+					{
+						LLTwitterConnect::instance().connectToTwitter(query_map["oauth_token"], query_map.get("oauth_verifier"));
+					}
+					return true;
+				}
+				else //if (tokens.size() >= 2 && tokens[1].asString() == "facebook")
+				{
+					// this command probably came from the fbc_web browser, so close it
+					LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web");
+					if (fbc_web)
+					{
+						fbc_web->closeFloater();
+					}
+
+					// connect to facebook
+					if (query_map.has("code"))
+					{
+						LLFacebookConnect::instance().connectToFacebook(query_map["code"], query_map.get("state"));
+					}
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+};
+LLSLShareHandler gSLShareHandler;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// DEPRECATED - please remove once "fbc" is phased out of the web service
 class LLFacebookConnectHandler : public LLCommandHandler
 {
 public:
-- 
cgit v1.2.3


From a36c4f45b4bf03c707089398bccf62a12ac44f0b Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 4 Dec 2013 18:02:04 -0800
Subject: ACME-1043 : WIP : Add an argument to open trusted content with js and
 other enabled options, bypassing prefs

---
 indra/newview/llfacebookconnect.cpp   | 10 +++++----
 indra/newview/llfloaterwebcontent.cpp |  6 ++++--
 indra/newview/llfloaterwebcontent.h   |  3 ++-
 indra/newview/llmediactrl.cpp         |  4 ++--
 indra/newview/llmediactrl.h           |  2 +-
 indra/newview/llviewermedia.cpp       | 39 ++++++++++++++++++++++-------------
 indra/newview/llviewermedia.h         |  5 +++--
 7 files changed, 43 insertions(+), 26 deletions(-)

diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index 0a662b4671..8cde871cd1 100644
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -377,10 +377,12 @@ void LLFacebookConnect::openFacebookWeb(std::string url)
 {
 	// Open the URL in an internal browser window without navigation UI
 	LLFloaterWebContent::Params p;
-    p.url(url).show_chrome(true);
-    p.url(url).allow_address_entry(false);
-    p.url(url).allow_back_forward_navigation(false);
-    p.url(url).trusted_content(true);
+    p.url(url);
+    p.show_chrome(true);
+    p.allow_address_entry(false);
+    p.allow_back_forward_navigation(false);
+    p.trusted_content(true);
+    p.clean_browser(true);
 	LLFloater *floater = LLFloaterReg::showInstance("fbc_web", p);
 	//the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems).
 	//So when showing the internal web browser, set focus to it's containing floater "fbc_web". When a mouse event 
diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp
index 814c91ef6c..2e08b3792f 100755
--- a/indra/newview/llfloaterwebcontent.cpp
+++ b/indra/newview/llfloaterwebcontent.cpp
@@ -53,7 +53,8 @@ LLFloaterWebContent::_Params::_Params()
     allow_back_forward_navigation("allow_back_forward_navigation", true),
 	preferred_media_size("preferred_media_size"),
 	trusted_content("trusted_content", false),
-	show_page_title("show_page_title", true)
+	show_page_title("show_page_title", true),
+    clean_browser("clean_browser", false)
 {}
 
 LLFloaterWebContent::LLFloaterWebContent( const Params& params )
@@ -240,11 +241,12 @@ void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p)
 
 void LLFloaterWebContent::open_media(const Params& p)
 {
+    llinfos << "Merov : LLFloaterWebContent::open_media, allow_address_entry = " << p.allow_address_entry << ", clean_browser = " << p.clean_browser << llendl;
 	// Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin.
 	LLViewerMedia::proxyWindowOpened(p.target(), p.id());
 	mWebBrowser->setHomePageUrl(p.url, "text/html");
 	mWebBrowser->setTarget(p.target);
-	mWebBrowser->navigateTo(p.url, "text/html");
+	mWebBrowser->navigateTo(p.url, "text/html", p.clean_browser);
 	
 	set_current_url(p.url);
 
diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h
index f22940cd07..2bb8e3271f 100755
--- a/indra/newview/llfloaterwebcontent.h
+++ b/indra/newview/llfloaterwebcontent.h
@@ -57,7 +57,8 @@ public:
 								allow_address_entry,
                                 allow_back_forward_navigation,
 								trusted_content,
-								show_page_title;
+								show_page_title,
+                                clean_browser;
 		Optional<LLRect>		preferred_media_size;
 
 		_Params();
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 2075aeed63..229542c1c4 100755
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -539,7 +539,7 @@ void LLMediaCtrl::clearCache()
 
 ////////////////////////////////////////////////////////////////////////////////
 //
-void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type)
+void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type, bool clean_browser)
 {
 	// don't browse to anything that starts with secondlife:// or sl://
 	const std::string protocol1 = "secondlife://";
@@ -556,7 +556,7 @@ void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type)
 	{
 		mCurrentNavUrl = url_in;
 		mMediaSource->setSize(mTextureWidth, mTextureHeight);
-		mMediaSource->navigateTo(url_in, mime_type, mime_type.empty());
+		mMediaSource->navigateTo(url_in, mime_type, mime_type.empty(), false, clean_browser);
 	}
 }
 
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
index 6c38c1fb56..8429d8188e 100755
--- a/indra/newview/llmediactrl.h
+++ b/indra/newview/llmediactrl.h
@@ -95,7 +95,7 @@ public:
 		virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
 
 		// navigation
-		void navigateTo( std::string url_in, std::string mime_type = "");
+		void navigateTo( std::string url_in, std::string mime_type = "", bool clean_browser = false);
 		void navigateBack();
 		void navigateHome();
 		void navigateForward();	
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 13483790ed..2393a932a2 100755
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -429,7 +429,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
 	// Try to find media with the same media ID
 	viewer_media_t media_impl = getMediaImplFromTextureID(media_entry->getMediaID());
 	
-	lldebugs << "called, current URL is \"" << media_entry->getCurrentURL() 
+	llinfos << "Merov : called, current URL is \"" << media_entry->getCurrentURL()
 			<< "\", previous URL is \"" << previous_url 
 			<< "\", update_from_self is " << (update_from_self?"true":"false")
 			<< llendl;
@@ -790,6 +790,8 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
 {
 	LLFastTimer t1(FTM_MEDIA_UPDATE);
 	
+    //llinfos << "Merov : updateMedia called" << llendl;
+    
 	// Enable/disable the plugin read thread
 	LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread"));
 	
@@ -1534,7 +1536,8 @@ void LLViewerMedia::createSpareBrowserMediaSource()
 	// popping up at the moment we start a media plugin.
 	if (!sSpareBrowserMediaSource && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))
 	{
-		// The null owner will keep the browser plugin from fully initializing 
+        llinfos << "Merov : createSpareBrowserMediaSource : need to create a spare browser..." << llendl;
+		// The null owner will keep the browser plugin from fully initializing
 		// (specifically, it keeps LLPluginClassMedia from negotiating a size change, 
 		// which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color)
 		sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", NULL, 0, 0);
@@ -1543,8 +1546,9 @@ void LLViewerMedia::createSpareBrowserMediaSource()
 
 /////////////////////////////////////////////////////////////////////////////////////////
 // static
-LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource() 
+LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource()
 {
+    llinfos << "Merov : getSpareBrowserMediaSource : give up the spare browser..." << llendl;
 	LLPluginClassMedia* result = sSpareBrowserMediaSource;
 	sSpareBrowserMediaSource = NULL;
 	return result; 
@@ -1592,7 +1596,8 @@ std::string LLViewerMedia::getParcelAudioURL()
 // static
 void LLViewerMedia::initClass()
 {
-	gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL);	
+    llinfos << "Merov : initClass called" << llendl;
+	gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL);
 	sTeleportFinishConnection = LLViewerParcelMgr::getInstance()->
 		setTeleportFinishedCallback(boost::bind(&LLViewerMedia::onTeleportFinished));
 }
@@ -1601,6 +1606,7 @@ void LLViewerMedia::initClass()
 // static
 void LLViewerMedia::cleanupClass()
 {
+    llinfos << "Merov : cleanupClass called" << llendl;
 	gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL);
 	sTeleportFinishConnection.disconnect();
 }
@@ -1669,7 +1675,8 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,
 	mNavigateSuspendedDeferred(false),
 	mIsUpdated(false),
 	mTrustedBrowser(false),
-	mZoomFactor(1.0)
+	mZoomFactor(1.0),
+    mCleanBrowser(false)
 { 
 
 	// Set up the mute list observer if it hasn't been set up already.
@@ -1793,14 +1800,15 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type)
 
 //////////////////////////////////////////////////////////////////////////////////////////
 /*static*/
-LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target)
+LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target, bool get_clean_source)
 {
 	std::string plugin_basename = LLMIMETypes::implType(media_type);
 	LLPluginClassMedia* media_source = NULL;
 	
 	// HACK: we always try to keep a spare running webkit plugin around to improve launch times.
 	// If a spare was already created before PluginAttachDebuggerToPlugins was set, don't use it.
-	if(plugin_basename == "media_plugin_webkit" && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))
+    // Merov : do not use a spare if launching with full viewer control (e.g. Facebook, Twitter and few others)
+	if(plugin_basename == "media_plugin_webkit" && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins") && !get_clean_source)
 	{
 		media_source = LLViewerMedia::getSpareBrowserMediaSource();
 		if(media_source)
@@ -1812,7 +1820,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
 			return media_source;
 		}
 	}
-	
+	llinfos << "Merov : newSourceFromMediaType, get_clean_source = " << get_clean_source << llendl;
 	if(plugin_basename.empty())
 	{
 		LL_WARNS_ONCE("Media") << "Couldn't find plugin for media type " << media_type << LL_ENDL;
@@ -1856,18 +1864,19 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
 
 			// collect 'cookies enabled' setting from prefs and send to embedded browser
 			bool cookies_enabled = gSavedSettings.getBOOL( "CookiesEnabled" );
-			media_source->enable_cookies( cookies_enabled );
+			media_source->enable_cookies( cookies_enabled || get_clean_source);
 
 			// collect 'plugins enabled' setting from prefs and send to embedded browser
 			bool plugins_enabled = gSavedSettings.getBOOL( "BrowserPluginsEnabled" );
-			media_source->setPluginsEnabled( plugins_enabled );
+			media_source->setPluginsEnabled( plugins_enabled  || get_clean_source);
 
 			// collect 'javascript enabled' setting from prefs and send to embedded browser
 			bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" );
-			media_source->setJavascriptEnabled( javascript_enabled );
+            llinfos << "Merov : setting javascript flag : " << javascript_enabled << llendl;
+			media_source->setJavascriptEnabled( javascript_enabled || get_clean_source);
 		
 			bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging");
-			media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled );
+			media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled  || get_clean_source);
 
 			media_source->setTarget(target);
 			
@@ -1922,7 +1931,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
 	// Save the MIME type that really caused the plugin to load
 	mCurrentMimeType = mMimeType;
 
-	LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mTarget);
+	LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mTarget, mCleanBrowser);
 	
 	if (media_source)
 	{
@@ -2543,7 +2552,7 @@ void LLViewerMediaImpl::unload()
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type,  bool rediscover_type, bool server_request)
+void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type,  bool rediscover_type, bool server_request, bool clean_browser)
 {
 	cancelMimeTypeProbe();
 
@@ -2554,8 +2563,10 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
 	}
 	
 	// Always set the current URL and MIME type.
+    llinfos << "Merov : LLViewerMediaImpl::navigateTo url = " << url << llendl;
 	mMediaURL = url;
 	mMimeType = mime_type;
+    mCleanBrowser = clean_browser;
 	
 	// Clear the current media URL, since it will no longer be correct.
 	mCurrentMediaURL.clear();
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index fff5b3fc08..07125e07e5 100755
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -234,7 +234,7 @@ public:
 	void navigateReload();
 	void navigateHome();
 	void unload();
-	void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false);
+	void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false, bool clean_browser = false);
 	void navigateInternal();
 	void navigateStop();
 	bool handleKeyHere(KEY key, MASK mask);
@@ -289,7 +289,7 @@ public:
 	void setTarget(const std::string& target) { mTarget = target; }
 	
 	// utility function to create a ready-to-use media instance from a desired media type.
-	static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target = LLStringUtil::null);
+	static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target = LLStringUtil::null, bool get_clean_source = false);
 
 	// Internally set our desired browser user agent string, including
 	// the Second Life version and skin name.  Used because we can
@@ -464,6 +464,7 @@ private:
 	bool mTrustedBrowser;
 	std::string mTarget;
 	LLNotificationPtr mNotification;
+    bool mCleanBrowser;     // force the creation of a clean browsing target with full options enabled
 
 private:
 	BOOL mIsUpdated ;
-- 
cgit v1.2.3


From f5b356a7d4b51fbf509926295cb38d3a1e8442e3 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 4 Dec 2013 21:14:40 -0800
Subject: ACME-1043 : Fixed! Added an argument to force a clean full feature
 browser window in some situations

---
 indra/newview/llfloaterwebcontent.cpp |  1 -
 indra/newview/llviewermedia.cpp       | 26 +++++++++-----------------
 indra/newview/llviewermedia.h         |  2 +-
 3 files changed, 10 insertions(+), 19 deletions(-)

diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp
index 2e08b3792f..4eb5236c6a 100755
--- a/indra/newview/llfloaterwebcontent.cpp
+++ b/indra/newview/llfloaterwebcontent.cpp
@@ -241,7 +241,6 @@ void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p)
 
 void LLFloaterWebContent::open_media(const Params& p)
 {
-    llinfos << "Merov : LLFloaterWebContent::open_media, allow_address_entry = " << p.allow_address_entry << ", clean_browser = " << p.clean_browser << llendl;
 	// Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin.
 	LLViewerMedia::proxyWindowOpened(p.target(), p.id());
 	mWebBrowser->setHomePageUrl(p.url, "text/html");
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 2393a932a2..1a19589a26 100755
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -429,7 +429,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
 	// Try to find media with the same media ID
 	viewer_media_t media_impl = getMediaImplFromTextureID(media_entry->getMediaID());
 	
-	llinfos << "Merov : called, current URL is \"" << media_entry->getCurrentURL()
+	lldebugs << "called, current URL is \"" << media_entry->getCurrentURL()
 			<< "\", previous URL is \"" << previous_url 
 			<< "\", update_from_self is " << (update_from_self?"true":"false")
 			<< llendl;
@@ -790,8 +790,6 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
 {
 	LLFastTimer t1(FTM_MEDIA_UPDATE);
 	
-    //llinfos << "Merov : updateMedia called" << llendl;
-    
 	// Enable/disable the plugin read thread
 	LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread"));
 	
@@ -1536,7 +1534,6 @@ void LLViewerMedia::createSpareBrowserMediaSource()
 	// popping up at the moment we start a media plugin.
 	if (!sSpareBrowserMediaSource && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))
 	{
-        llinfos << "Merov : createSpareBrowserMediaSource : need to create a spare browser..." << llendl;
 		// The null owner will keep the browser plugin from fully initializing
 		// (specifically, it keeps LLPluginClassMedia from negotiating a size change, 
 		// which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color)
@@ -1548,7 +1545,6 @@ void LLViewerMedia::createSpareBrowserMediaSource()
 // static
 LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource()
 {
-    llinfos << "Merov : getSpareBrowserMediaSource : give up the spare browser..." << llendl;
 	LLPluginClassMedia* result = sSpareBrowserMediaSource;
 	sSpareBrowserMediaSource = NULL;
 	return result; 
@@ -1596,7 +1592,6 @@ std::string LLViewerMedia::getParcelAudioURL()
 // static
 void LLViewerMedia::initClass()
 {
-    llinfos << "Merov : initClass called" << llendl;
 	gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL);
 	sTeleportFinishConnection = LLViewerParcelMgr::getInstance()->
 		setTeleportFinishedCallback(boost::bind(&LLViewerMedia::onTeleportFinished));
@@ -1606,7 +1601,6 @@ void LLViewerMedia::initClass()
 // static
 void LLViewerMedia::cleanupClass()
 {
-    llinfos << "Merov : cleanupClass called" << llendl;
 	gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL);
 	sTeleportFinishConnection.disconnect();
 }
@@ -1800,15 +1794,16 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type)
 
 //////////////////////////////////////////////////////////////////////////////////////////
 /*static*/
-LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target, bool get_clean_source)
+LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target, bool clean_browser)
 {
 	std::string plugin_basename = LLMIMETypes::implType(media_type);
 	LLPluginClassMedia* media_source = NULL;
 	
 	// HACK: we always try to keep a spare running webkit plugin around to improve launch times.
 	// If a spare was already created before PluginAttachDebuggerToPlugins was set, don't use it.
-    // Merov : do not use a spare if launching with full viewer control (e.g. Facebook, Twitter and few others)
-	if(plugin_basename == "media_plugin_webkit" && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins") && !get_clean_source)
+    // Do not use a spare if launching with full viewer control (e.g. Facebook, Twitter and few others)
+	if ((plugin_basename == "media_plugin_webkit") &&
+        !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins") && !clean_browser)
 	{
 		media_source = LLViewerMedia::getSpareBrowserMediaSource();
 		if(media_source)
@@ -1820,7 +1815,6 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
 			return media_source;
 		}
 	}
-	llinfos << "Merov : newSourceFromMediaType, get_clean_source = " << get_clean_source << llendl;
 	if(plugin_basename.empty())
 	{
 		LL_WARNS_ONCE("Media") << "Couldn't find plugin for media type " << media_type << LL_ENDL;
@@ -1864,19 +1858,18 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
 
 			// collect 'cookies enabled' setting from prefs and send to embedded browser
 			bool cookies_enabled = gSavedSettings.getBOOL( "CookiesEnabled" );
-			media_source->enable_cookies( cookies_enabled || get_clean_source);
+			media_source->enable_cookies( cookies_enabled || clean_browser);
 
 			// collect 'plugins enabled' setting from prefs and send to embedded browser
 			bool plugins_enabled = gSavedSettings.getBOOL( "BrowserPluginsEnabled" );
-			media_source->setPluginsEnabled( plugins_enabled  || get_clean_source);
+			media_source->setPluginsEnabled( plugins_enabled  || clean_browser);
 
 			// collect 'javascript enabled' setting from prefs and send to embedded browser
 			bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" );
-            llinfos << "Merov : setting javascript flag : " << javascript_enabled << llendl;
-			media_source->setJavascriptEnabled( javascript_enabled || get_clean_source);
+			media_source->setJavascriptEnabled( javascript_enabled || clean_browser);
 		
 			bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging");
-			media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled  || get_clean_source);
+			media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled  || clean_browser);
 
 			media_source->setTarget(target);
 			
@@ -2563,7 +2556,6 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
 	}
 	
 	// Always set the current URL and MIME type.
-    llinfos << "Merov : LLViewerMediaImpl::navigateTo url = " << url << llendl;
 	mMediaURL = url;
 	mMimeType = mime_type;
     mCleanBrowser = clean_browser;
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 07125e07e5..6803adfaa2 100755
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -289,7 +289,7 @@ public:
 	void setTarget(const std::string& target) { mTarget = target; }
 	
 	// utility function to create a ready-to-use media instance from a desired media type.
-	static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target = LLStringUtil::null, bool get_clean_source = false);
+	static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target = LLStringUtil::null, bool clean_browser = false);
 
 	// Internally set our desired browser user agent string, including
 	// the Second Life version and skin name.  Used because we can
-- 
cgit v1.2.3


From 11e3f8c3a1209c17814d90978a1c0b80225bc122 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Thu, 5 Dec 2013 12:54:15 -0800
Subject: ACME-1043 : Use a clean browser for connection to Flickr and Twitter
 as well

---
 indra/newview/llflickrconnect.cpp  | 10 ++++++----
 indra/newview/lltwitterconnect.cpp | 10 ++++++----
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp
index 3a21933b63..8f9f55c1ea 100644
--- a/indra/newview/llflickrconnect.cpp
+++ b/indra/newview/llflickrconnect.cpp
@@ -276,10 +276,12 @@ void LLFlickrConnect::openFlickrWeb(std::string url)
 {
 	// Open the URL in an internal browser window without navigation UI
 	LLFloaterWebContent::Params p;
-    p.url(url).show_chrome(true);
-    p.url(url).allow_address_entry(false);
-    p.url(url).allow_back_forward_navigation(false);
-    p.url(url).trusted_content(true);
+    p.url(url);
+    p.show_chrome(true);
+    p.allow_address_entry(false);
+    p.allow_back_forward_navigation(false);
+    p.trusted_content(true);
+    p.clean_browser(true);
 	LLFloater *floater = LLFloaterReg::showInstance("flickr_web", p);
 	//the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems).
 	//So when showing the internal web browser, set focus to it's containing floater "flickr_web". When a mouse event 
diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp
index e015867df2..7942b21319 100644
--- a/indra/newview/lltwitterconnect.cpp
+++ b/indra/newview/lltwitterconnect.cpp
@@ -276,10 +276,12 @@ void LLTwitterConnect::openTwitterWeb(std::string url)
 {
 	// Open the URL in an internal browser window without navigation UI
 	LLFloaterWebContent::Params p;
-    p.url(url).show_chrome(true);
-    p.url(url).allow_address_entry(false);
-    p.url(url).allow_back_forward_navigation(false);
-    p.url(url).trusted_content(true);
+    p.url(url);
+    p.show_chrome(true);
+    p.allow_address_entry(false);
+    p.allow_back_forward_navigation(false);
+    p.trusted_content(true);
+    p.clean_browser(true);
 	LLFloater *floater = LLFloaterReg::showInstance("twitter_web", p);
 	//the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems).
 	//So when showing the internal web browser, set focus to it's containing floater "twitter_web". When a mouse event 
-- 
cgit v1.2.3


From 88f139594bb819bc31b438edcceaf9cd661b3f82 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Tue, 10 Dec 2013 18:55:49 +0000
Subject: Added placeholder http SLURL for Twitter sharing on Aditi for
 ACME-1216

---
 indra/newview/llfloatertwitter.cpp | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index 18a1fcbba9..ea263566a6 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -53,6 +53,7 @@ static LLRegisterPanelClassWrapper<LLTwitterPhotoPanel> t_panel_photo("lltwitter
 static LLRegisterPanelClassWrapper<LLTwitterAccountPanel> t_panel_account("lltwitteraccountpanel");
 
 const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
+const std::string DEFAULT_PHOTO_LOCATION_URL = "http://maps.secondlife.com/";
 const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=twitter&utm_medium=photo&utm_campaign=slshare";
 
 ///////////////////////////
@@ -271,6 +272,13 @@ void LLTwitterPhotoPanel::sendPhoto()
 		LLAgentUI::buildSLURL(slurl);
 		std::string slurl_string = slurl.getSLURLString();
 
+		// Use a valid http:// URL if the scheme is secondlife:// 
+		LLURI slurl_uri(slurl_string);
+		if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME)
+		{
+			slurl_string = DEFAULT_PHOTO_LOCATION_URL;
+		}
+
 		// Add query parameters so Google Analytics can track incoming clicks!
 		slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS;
 
@@ -281,7 +289,6 @@ void LLTwitterPhotoPanel::sendPhoto()
 			status = status + " " + slurl_string;
 	}
 
-
 	// Add the photo if required
 	bool add_photo = mPhotoCheckbox->getValue().asBoolean();
 	if (add_photo)
-- 
cgit v1.2.3


From 26a6668fb23ce289b67154ba3e3ac35f25a54978 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 11 Dec 2013 21:46:17 -0800
Subject: ACME-1233 : Set the quality for jpeg images send to Facebook
 correctly

---
 indra/newview/llfloaterfacebook.cpp                | 36 +++++++++++++++++++---
 indra/newview/llfloaterfacebook.h                  |  2 ++
 indra/newview/llsnapshotlivepreview.cpp            | 10 ++++--
 indra/newview/llsnapshotlivepreview.h              |  2 +-
 .../skins/default/xui/en/panel_facebook_photo.xml  |  4 +++
 5 files changed, 47 insertions(+), 7 deletions(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 6488e7ea00..09cc14f6db 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -59,6 +59,13 @@ const std::string DEFAULT_CHECKIN_ICON_URL = "http://map.secondlife.com.s3.amazo
 const std::string DEFAULT_CHECKIN_QUERY_PARAMETERS = "?sourceid=slshare_checkin&utm_source=facebook&utm_medium=checkin&utm_campaign=slshare";
 const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=facebook&utm_medium=photo&utm_campaign=slshare";
 
+const S32 MAX_QUALITY = 100;        // Max quality value for jpeg images
+const S32 MIN_QUALITY = 0;          // Min quality value for jpeg images
+const S32 TARGET_DATA_SIZE = 95000; // Size of the image (compressed) we're trying to send to Facebook
+const S32 MAX_DATA_SIZE = 98000;    // Max size of the image (compressed) sent to Facebook
+const S32 QUALITY_DECREMENT = 5;    // Value we use to ratchet the quality down if we're over MAX_DATA_SIZE
+
+
 std::string get_map_url()
 {
     LLVector3d center_agent;
@@ -73,6 +80,14 @@ std::string get_map_url()
     return map_url;
 }
 
+// Compute target jpeg quality : see https://wiki.lindenlab.com/wiki/Facebook_Image_Quality for details
+S32 compute_jpeg_quality(S32 width, S32 height)
+{
+    F32 target_compression_ratio = (F32)(width * height * 3) / (F32)(TARGET_DATA_SIZE);
+    S32 quality = (S32)(110.0f - (2.0f * target_compression_ratio));
+    return llclamp(quality,MIN_QUALITY,MAX_QUALITY);
+}
+
 ///////////////////////////
 //LLFacebookStatusPanel//////
 ///////////////////////////
@@ -173,7 +188,8 @@ mWorkingLabel(NULL),
 mThumbnailPlaceholder(NULL),
 mCaptionTextBox(NULL),
 mLocationCheckbox(NULL),
-mPostButton(NULL)
+mPostButton(NULL),
+mQuality(MAX_QUALITY)
 {
 	mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFacebookPhotoPanel::onSend, this));
 	mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFacebookPhotoPanel::onClickNewSnapshot, this));
@@ -285,10 +301,11 @@ void LLFacebookPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
 			p.rect(full_screen_rect);
 			LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
 			mPreviewHandle = previewp->getHandle();	
+            mQuality = MAX_QUALITY;
 
 			previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
 			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
-			//previewp->setSnapshotQuality(98);
+			previewp->setSnapshotQuality(mQuality, false);
 			previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
 
 			updateControls();
@@ -399,6 +416,11 @@ void LLFacebookPhotoPanel::updateControls()
 	if (got_snap)
 	{
 		LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 );
+        if (previewp->getDataSize() >= MAX_DATA_SIZE)
+        {
+            // If size too big, change mQuality
+            mQuality -= QUALITY_DECREMENT;
+        }
 	}
 
 	//getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown")); <---uses localized string
@@ -445,8 +467,14 @@ void LLFacebookPhotoPanel::updateResolution(BOOL do_update)
 		checkAspectRatio(width);
 
 		previewp->getSize(width, height);
+        if (do_update || (mQuality == MAX_QUALITY))
+        {
+            // Recompute quality setting if the update is requested by the UI or if quality has been reset
+            mQuality = compute_jpeg_quality(width, height);
+        }
+        bool quality_reset = previewp->setSnapshotQuality(mQuality, false);
 		
-		if(original_width != width || original_height != height)
+		if (original_width != width || original_height != height || quality_reset)
 		{
 			previewp->setSize(width, height);
 
@@ -454,7 +482,7 @@ void LLFacebookPhotoPanel::updateResolution(BOOL do_update)
 			lldebugs << "updating thumbnail" << llendl;
 			
 			previewp->updateSnapshot(FALSE, TRUE);
-			if(do_update)
+			if (do_update || quality_reset)
 			{
 				lldebugs << "Will update controls" << llendl;
 				updateControls();
diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h
index ab6420264b..0776f24034 100644
--- a/indra/newview/llfloaterfacebook.h
+++ b/indra/newview/llfloaterfacebook.h
@@ -88,6 +88,8 @@ private:
 	LLUICtrl * mLocationCheckbox;
 	LLUICtrl * mPostButton;
 	LLUICtrl* mCancelButton;
+    
+    S32 mQuality;       // Compression quality
 };
 
 class LLFacebookCheckinPanel : public LLPanel
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 9feeea1644..7f578975db 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -222,15 +222,21 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail
 	}
 }
 
-void LLSnapshotLivePreview::setSnapshotQuality(S32 quality)
+// Return true if the quality has been changed, false otherwise
+bool LLSnapshotLivePreview::setSnapshotQuality(S32 quality, bool set_by_user)
 {
 	llclamp(quality, 0, 100);
 	if (quality != mSnapshotQuality)
 	{
 		mSnapshotQuality = quality;
-		gSavedSettings.setS32("SnapshotQuality", quality);
+        if (set_by_user)
+        {
+            gSavedSettings.setS32("SnapshotQuality", quality);
+        }
 		mSnapshotUpToDate = FALSE;
+        return true;
 	}
+    return false;
 }
 
 void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y)
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index fe3d257b02..0c63bf47c7 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -93,7 +93,7 @@ public:
 
 	void setSnapshotType(ESnapshotType type) { mSnapshotType = type; }
 	void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; }
-	void setSnapshotQuality(S32 quality);
+	bool setSnapshotQuality(S32 quality, bool set_by_user = true);
 	void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
 	void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f);
 	void saveWeb();
diff --git a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
index 19f9f2fb74..2d46665bae 100644
--- a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
@@ -39,6 +39,10 @@
                label="1024x768"
                name="1024x768"
                value="[i1024,i768]" />
+              <combo_box.item
+               label="1200x630"
+               name="1200x630"
+               value="[i1200,i630]" />
             </combo_box>
             <text
              follows="left|top"
-- 
cgit v1.2.3


From 798d62a467035e255ef172e0be1f707ba15f5d04 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Mon, 16 Dec 2013 15:20:53 -0800
Subject: ACME-1233 : Avoid iteration on the quality setting and make it more
 consistent

---
 indra/newview/llfloaterfacebook.cpp | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 09cc14f6db..7bf74ef6ba 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -62,9 +62,6 @@ const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_
 const S32 MAX_QUALITY = 100;        // Max quality value for jpeg images
 const S32 MIN_QUALITY = 0;          // Min quality value for jpeg images
 const S32 TARGET_DATA_SIZE = 95000; // Size of the image (compressed) we're trying to send to Facebook
-const S32 MAX_DATA_SIZE = 98000;    // Max size of the image (compressed) sent to Facebook
-const S32 QUALITY_DECREMENT = 5;    // Value we use to ratchet the quality down if we're over MAX_DATA_SIZE
-
 
 std::string get_map_url()
 {
@@ -416,11 +413,6 @@ void LLFacebookPhotoPanel::updateControls()
 	if (got_snap)
 	{
 		LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 );
-        if (previewp->getDataSize() >= MAX_DATA_SIZE)
-        {
-            // If size too big, change mQuality
-            mQuality -= QUALITY_DECREMENT;
-        }
 	}
 
 	//getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown")); <---uses localized string
@@ -467,11 +459,9 @@ void LLFacebookPhotoPanel::updateResolution(BOOL do_update)
 		checkAspectRatio(width);
 
 		previewp->getSize(width, height);
-        if (do_update || (mQuality == MAX_QUALITY))
-        {
-            // Recompute quality setting if the update is requested by the UI or if quality has been reset
-            mQuality = compute_jpeg_quality(width, height);
-        }
+        
+        // Recompute quality setting
+        mQuality = compute_jpeg_quality(width, height);
         bool quality_reset = previewp->setSnapshotQuality(mQuality, false);
 		
 		if (original_width != width || original_height != height || quality_reset)
-- 
cgit v1.2.3


From be80b11d3063cc1b394ed604901418ba421cd86c Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 18 Dec 2013 11:12:46 -0800
Subject: Fix FFLOAD_ALL issue in file picker, add FFLOAD_EXE to fix exe
 picking on Mac Cocoa

---
 indra/newview/llfilepicker.cpp       | 11 ++++++++---
 indra/newview/llfilepicker.h         |  3 ++-
 indra/newview/llfloateruipreview.cpp |  7 +++----
 indra/newview/llviewermenufile.cpp   |  3 ++-
 4 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 16eacc9392..f921dace84 100755
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -167,7 +167,8 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
 	BOOL res = TRUE;
 	switch (filter)
 	{
-	case FFLOAD_ALL:
+    case FFLOAD_ALL:
+    case FFLOAD_EXE:
 		mOFN.lpstrFilter = L"All Files (*.*)\0*.*\0" \
 		SOUND_FILTER \
 		IMAGE_FILTER \
@@ -579,6 +580,10 @@ std::vector<std::string>* LLFilePicker::navOpenFilterProc(ELoadFilter filter) //
             allowedv->push_back("tpic");
             allowedv->push_back("png");
             break;
+        case FFLOAD_EXE:
+            allowedv->push_back("app");
+            allowedv->push_back("exe");
+            break;
         case FFLOAD_WAV:
             allowedv->push_back("wav");
             break;
@@ -777,9 +782,9 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
         mPickOptions &= ~F_FILE;
     }
 
-	if(filter == FFLOAD_ALL)	// allow application bundles etc. to be traversed; important for DEV-16869, but generally useful
+	if (filter == FFLOAD_ALL)	// allow application bundles etc. to be traversed; important for DEV-16869, but generally useful
 	{
-        mPickOptions &= F_NAV_SUPPORT;
+        mPickOptions |= F_NAV_SUPPORT;
 	}
 	
 	if (blocking)
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index f0f82c51db..0b89e2716c 100755
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -86,7 +86,8 @@ public:
 		FFLOAD_COLLADA = 10,
 		FFLOAD_SCRIPT = 11,
 		FFLOAD_DICTIONARY = 12,
-        FFLOAD_DIRECTORY = 13   //To call from lldirpicker. 
+        FFLOAD_DIRECTORY = 13,   // To call from lldirpicker.
+        FFLOAD_EXE = 14          // Note: EXE will be treated as ALL on Windows and Linux but not on Darwin
 	};
 
 	enum ESaveFilter
diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp
index 0106a1615d..44649e6ca8 100755
--- a/indra/newview/llfloateruipreview.cpp
+++ b/indra/newview/llfloateruipreview.cpp
@@ -1020,12 +1020,11 @@ void LLFloaterUIPreview::onClickEditFloater()
 // Respond to button click to browse for an executable with which to edit XML files
 void LLFloaterUIPreview::onClickBrowseForEditor()
 {
-	// create load dialog box
-	LLFilePicker::ELoadFilter type = (LLFilePicker::ELoadFilter)((intptr_t)((void*)LLFilePicker::FFLOAD_ALL));	// nothing for *.exe so just use all
+	// Let the user choose an executable through the file picker dialog box
 	LLFilePicker& picker = LLFilePicker::instance();
-	if (!picker.getOpenFile(type))	// user cancelled -- do nothing
+    if (!picker.getOpenFile(LLFilePicker::FFLOAD_EXE))
 	{
-		return;
+		return; // user cancelled -- do nothing
 	}
 
 	// put the selected path into text field
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index be78603e2d..a17dd953ad 100755
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -215,7 +215,8 @@ std::string build_extensions_string(LLFilePicker::ELoadFilter filter)
 #endif
 	case LLFilePicker::FFLOAD_XML:
 	    return XML_EXTENSIONS;
-	case LLFilePicker::FFLOAD_ALL:
+    case LLFilePicker::FFLOAD_ALL:
+    case LLFilePicker::FFLOAD_EXE:
 		return ALL_FILE_EXTENSIONS;
 #endif
     default:
-- 
cgit v1.2.3


From e88c9909b627502db55aa85ba8b2947039818e60 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Wed, 18 Dec 2013 22:24:21 +0000
Subject: Added highlighting to SLShare tabs for ACME-1177

---
 indra/newview/llfacebookconnect.cpp                     | 1 +
 indra/newview/skins/default/xui/en/floater_facebook.xml | 3 ++-
 indra/newview/skins/default/xui/en/floater_flickr.xml   | 3 ++-
 indra/newview/skins/default/xui/en/floater_twitter.xml  | 3 ++-
 4 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index eeb28376a9..77c67b1779 100644
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -468,6 +468,7 @@ std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, b
     LLViewerRegion *regionp = gAgent.getRegion();
     if (regionp)
     {
+		//url = "http://pdp15.lindenlab.com/facebook/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
         url = regionp->getCapability("FacebookConnect");
         url += route;
     
diff --git a/indra/newview/skins/default/xui/en/floater_facebook.xml b/indra/newview/skins/default/xui/en/floater_facebook.xml
index 820e105e53..c1ff8571e9 100644
--- a/indra/newview/skins/default/xui/en/floater_facebook.xml
+++ b/indra/newview/skins/default/xui/en/floater_facebook.xml
@@ -28,7 +28,8 @@
      tab_position="top"
      top="7"
      height="437"
-     halign="center">
+     halign="center"
+     use_highlighting_on_hover="true">
      <panel
        filename="panel_facebook_status.xml"
        class="llfacebookstatuspanel"
diff --git a/indra/newview/skins/default/xui/en/floater_flickr.xml b/indra/newview/skins/default/xui/en/floater_flickr.xml
index 57014f8427..1a9ffd0489 100644
--- a/indra/newview/skins/default/xui/en/floater_flickr.xml
+++ b/indra/newview/skins/default/xui/en/floater_flickr.xml
@@ -28,7 +28,8 @@
      tab_position="top"
      top="7"
      height="577"
-     halign="center">
+     halign="center"
+     use_highlighting_on_hover="true">
      <panel
        filename="panel_flickr_photo.xml"
        class="llflickrphotopanel"
diff --git a/indra/newview/skins/default/xui/en/floater_twitter.xml b/indra/newview/skins/default/xui/en/floater_twitter.xml
index 751914141c..aa5bfce2e9 100644
--- a/indra/newview/skins/default/xui/en/floater_twitter.xml
+++ b/indra/newview/skins/default/xui/en/floater_twitter.xml
@@ -28,7 +28,8 @@
      tab_position="top"
      top="7"
      height="457"
-     halign="center">
+     halign="center"
+     use_highlighting_on_hover="true">
      <panel
        filename="panel_twitter_photo.xml"
        class="lltwitterphotopanel"
-- 
cgit v1.2.3


From 19d482e913e66f76f3bb7a3e1048e35853be535f Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Wed, 18 Dec 2013 23:18:02 +0000
Subject: Cleaned up some code while investigated ACME-1152

---
 indra/newview/llfacebookconnect.cpp | 36 ++++++------------------------------
 1 file changed, 6 insertions(+), 30 deletions(-)

diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index 77c67b1779..eb044d90cd 100644
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -83,11 +83,7 @@ public:
 				if (tokens.size() >= 2 && tokens[1].asString() == "flickr")
 				{
 					// this command probably came from the flickr_web browser, so close it
-					LLFloater* flickr_web = LLFloaterReg::getInstance("flickr_web");
-					if (flickr_web)
-					{
-						flickr_web->closeFloater();
-					}
+					LLFloaterReg::hideInstance("flickr_web");
 
 					// connect to flickr
 					if (query_map.has("oauth_token"))
@@ -99,11 +95,7 @@ public:
 				else if (tokens.size() >= 2 && tokens[1].asString() == "twitter")
 				{
 					// this command probably came from the twitter_web browser, so close it
-					LLFloater* twitter_web = LLFloaterReg::getInstance("twitter_web");
-					if (twitter_web)
-					{
-						twitter_web->closeFloater();
-					}
+					LLFloaterReg::hideInstance("twitter_web");
 
 					// connect to twitter
 					if (query_map.has("oauth_token"))
@@ -115,11 +107,7 @@ public:
 				else //if (tokens.size() >= 2 && tokens[1].asString() == "facebook")
 				{
 					// this command probably came from the fbc_web browser, so close it
-					LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web");
-					if (fbc_web)
-					{
-						fbc_web->closeFloater();
-					}
+					LLFloaterReg::hideInstance("fbc_web");
 
 					// connect to facebook
 					if (query_map.has("code"))
@@ -152,11 +140,7 @@ public:
 				if (tokens.size() >= 2 && tokens[1].asString() == "flickr")
 				{
 					// this command probably came from the flickr_web browser, so close it
-					LLFloater* flickr_web = LLFloaterReg::getInstance("flickr_web");
-					if (flickr_web)
-					{
-						flickr_web->closeFloater();
-					}
+					LLFloaterReg::hideInstance("flickr_web");
 
 					// connect to flickr
 					if (query_map.has("oauth_token"))
@@ -168,11 +152,7 @@ public:
 				else if (tokens.size() >= 2 && tokens[1].asString() == "twitter")
 				{
 					// this command probably came from the twitter_web browser, so close it
-					LLFloater* twitter_web = LLFloaterReg::getInstance("twitter_web");
-					if (twitter_web)
-					{
-						twitter_web->closeFloater();
-					}
+					LLFloaterReg::hideInstance("twitter_web");
 
 					// connect to twitter
 					if (query_map.has("oauth_token"))
@@ -184,11 +164,7 @@ public:
 				else //if (tokens.size() >= 2 && tokens[1].asString() == "facebook")
 				{
 					// this command probably came from the fbc_web browser, so close it
-					LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web");
-					if (fbc_web)
-					{
-						fbc_web->closeFloater();
-					}
+					LLFloaterReg::hideInstance("fbc_web");
 
 					// connect to facebook
 					if (query_map.has("code"))
-- 
cgit v1.2.3


From 6578144b7eda1dae885e5cc172751203b1d16c2d Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 18 Dec 2013 15:55:13 -0800
Subject: ACME-1236 : WIP : Added Gray Scale as an experimental filter in
 Flickr. Lots of ugly hacks for now

---
 indra/llimage/llimage.cpp                          | 20 ++++++++++++++
 indra/llimage/llimage.h                            |  3 ++
 indra/newview/llfloaterflickr.cpp                  | 32 ++++++++++------------
 indra/newview/llfloaterflickr.h                    |  1 +
 indra/newview/llsnapshotlivepreview.cpp            | 16 +++++++++--
 indra/newview/llsnapshotlivepreview.h              |  3 ++
 .../skins/default/xui/en/panel_flickr_photo.xml    | 31 ++++++++++++---------
 7 files changed, 73 insertions(+), 33 deletions(-)

diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index c8a05e1fae..e5281feff0 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -933,6 +933,26 @@ BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
 	return TRUE ;
 }
 
+// *TODO : Implement real color transform
+// Merov : This is temporary code for testing... 
+void LLImageRaw::colorTransform()
+{
+	const S32 components = getComponents();
+	llassert( components >= 1 && components <= 4 );
+    
+	S32 pixels = getWidth() * getHeight();
+	U8* dst_data = getData();
+    llinfos << "Merov : Convert the image to Black and White!!! pixels = " << pixels << ", comp = " << components << llendl;
+	for( S32 i=0; i<pixels; i++ )
+	{
+        U8 gray = (U8)(((U32)(dst_data[0]) + (U32)(dst_data[1]) + (U32)(dst_data[2]))/3);
+		dst_data[0] = gray;
+		dst_data[1] = gray;
+		dst_data[2] = gray;
+		dst_data += components;
+	}
+}
+
 void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step )
 {
 	const S32 components = getComponents();
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 2277afc585..96c37f5436 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -255,6 +255,9 @@ public:
 
 	// Src and dst are same size.  Src has 4 components.  Dst has 3 components.
 	void compositeUnscaled4onto3( LLImageRaw* src );
+    
+    // Filter operations
+    void colorTransform();
 
 protected:
 	// Create an image from a local file (generally used in tools)
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 0a4c3f091b..675266143d 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -92,6 +92,8 @@ BOOL LLFlickrPhotoPanel::postBuild()
 	mSnapshotPanel = getChild<LLUICtrl>("snapshot_panel");
 	mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
 	mResolutionComboBox->setCommitCallback(boost::bind(&LLFlickrPhotoPanel::updateResolution, this, TRUE));
+	mFilterComboBox = getChild<LLUICtrl>("filters_combobox");
+	mFilterComboBox->setCommitCallback(boost::bind(&LLFlickrPhotoPanel::updateResolution, this, TRUE));
 	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
     mWorkingLabel = getChild<LLUICtrl>("working_lbl");
 	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
@@ -301,33 +303,18 @@ void LLFlickrPhotoPanel::clearAndClose()
 void LLFlickrPhotoPanel::updateControls()
 {
 	LLSnapshotLivePreview* previewp = getPreviewView();
-	BOOL got_bytes = previewp && previewp->getDataSize() > 0;
 	BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
-	LLSnapshotLivePreview::ESnapshotType shot_type = (previewp ? previewp->getSnapshotType() : LLSnapshotLivePreview::SNAPSHOT_POSTCARD);
 
 	// *TODO: Separate maximum size for Web images from postcards
 	lldebugs << "Is snapshot up-to-date? " << got_snap << llendl;
 
-	LLLocale locale(LLLocale::USER_LOCALE);
-	std::string bytes_string;
-	if (got_snap)
-	{
-		LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 );
-	}
-
-	//getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown")); <---uses localized string
-	getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : "unknown");
-	getChild<LLUICtrl>("file_size_label")->setColor(
-		shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD 
-		&& got_bytes
-		&& previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" ));
-
 	updateResolution(FALSE);
 }
 
 void LLFlickrPhotoPanel::updateResolution(BOOL do_update)
 {
-	LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox);
+	LLComboBox* combobox  = static_cast<LLComboBox *>(mResolutionComboBox);
+	LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
 
 	std::string sdstring = combobox->getSelectedValue();
 	LLSD sdres;
@@ -336,6 +323,9 @@ void LLFlickrPhotoPanel::updateResolution(BOOL do_update)
 
 	S32 width = sdres[0];
 	S32 height = sdres[1];
+    
+    const std::string& filter_name = filterbox->getSimple();
+    llinfos << "Merov : filter name is : " << filter_name << llendl;
 
 	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
 	if (previewp && combobox->getCurrentIndex() >= 0)
@@ -359,10 +349,16 @@ void LLFlickrPhotoPanel::updateResolution(BOOL do_update)
 		checkAspectRatio(width);
 
 		previewp->getSize(width, height);
+        // Merov : 
+        // Get the old filter, compare to the current one "filter_name" and set if changed
+        // If changed, also force the updateSnapshot() here under
+        S32 original_filter = previewp->getFilter();
+        S32 filter = ("Gray Scale" == filter_name ? 1 : 0);
 		
-		if(original_width != width || original_height != height)
+		if ((original_width != width) || (original_height != height) || (original_filter != filter))
 		{
 			previewp->setSize(width, height);
+            previewp->setFilter(filter);
 
 			// hide old preview as the aspect ratio could be wrong
 			lldebugs << "updating thumbnail" << llendl;
diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h
index 9a329d4451..1d9e649899 100644
--- a/indra/newview/llfloaterflickr.h
+++ b/indra/newview/llfloaterflickr.h
@@ -63,6 +63,7 @@ private:
 
 	LLUICtrl * mSnapshotPanel;
 	LLUICtrl * mResolutionComboBox;
+	LLUICtrl * mFilterComboBox;
 	LLUICtrl * mRefreshBtn;
 	LLUICtrl * mWorkingLabel;
 	LLUICtrl * mThumbnailPlaceholder;
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 7f578975db..ab9788a88b 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -89,7 +89,8 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param
 	mCameraPos(LLViewerCamera::getInstance()->getOrigin()),
 	mCameraRot(LLViewerCamera::getInstance()->getQuaternion()),
 	mSnapshotActive(FALSE),
-	mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR)
+	mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR),
+    mFilterType(0)
 {
 	setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality"));
 	mSnapshotDelayTimer.setTimerExpirySec(0.0f);
@@ -585,7 +586,12 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
 	if(raw)
 	{
 		raw->expandToPowerOfTwo();
-		mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); 		
+        // Merov : Filter also the thumbnail?
+        if (getFilter() == 1)
+        {
+            raw->colorTransform();
+        }
+		mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
 		mThumbnailUpToDate = TRUE ;
 	}
 
@@ -689,6 +695,12 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 		}
 		else
 		{
+            // Merov : Time to apply the filter to mPreviewImage!!!
+            if (previewp->getFilter() == 1)
+            {
+                previewp->mPreviewImage->colorTransform();
+            }
+            
 			// delete any existing image
 			previewp->mFormattedImage = NULL;
 			// now create the new one of the appropriate format.
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index 0c63bf47c7..d5ae3b491b 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -95,6 +95,8 @@ public:
 	void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; }
 	bool setSnapshotQuality(S32 quality, bool set_by_user = true);
 	void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
+    void setFilter(S32 filter) { mFilterType = filter; }
+    S32  getFilter() { return mFilterType; }
 	void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f);
 	void saveWeb();
 	void saveTexture();
@@ -154,6 +156,7 @@ private:
 	LLQuaternion				mCameraRot;
 	BOOL						mSnapshotActive;
 	LLViewerWindow::ESnapshotType mSnapshotBufferType;
+    S32                         mFilterType; // *TODO: eventually use a string and a named filter
 
 public:
 	static std::set<LLSnapshotLivePreview*> sList;
diff --git a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
index b3af271f34..28e3557e15 100644
--- a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
@@ -40,19 +40,24 @@
                name="1024x768"
                value="[i1024,i768]" />
             </combo_box>
-            <text
-             follows="left|top"
-             font="SansSerifSmall"
-             height="14"
-             left="208"
-             length="1"
-             halign="right"
-             name="file_size_label"
-             top="9"
-             type="string"
-             width="50">
-              [SIZE] KB
-            </text>
+            <combo_box
+               control_name="SocialPhotoFilters"
+               follows="right|top"
+               name="filters_combobox"
+               tool_tip="Image filters"
+               top="6"
+               left="165"
+               height="21"
+               width="135">
+                <combo_box.item
+                 label="No Filter"
+                 name="NoFilter"
+                 value="NoFilter" />
+                <combo_box.item
+                 label="Gray Scale"
+                 name="GrayScale"
+                 value="GrayScale" />
+            </combo_box>
             <panel
                 height="150"
                 width="250"
-- 
cgit v1.2.3


From 7372afaae4aa7097ffad1e9c070b8b9d9a611f62 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Fri, 20 Dec 2013 13:49:20 -0800
Subject: ACME-1236 : WIP : Implement colorTransform filter, grayscale and
 sepia using it, add parameter to llimage_libtest to use filters

---
 .../llimage_libtest/llimage_libtest.cpp            | 34 +++++++++++++++++++
 indra/llimage/llimage.cpp                          | 38 +++++++++++++++++-----
 indra/llimage/llimage.h                            |  8 +++--
 indra/newview/llsnapshotlivepreview.cpp            |  4 +--
 4 files changed, 72 insertions(+), 12 deletions(-)

diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 034c816742..e485136f58 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -83,6 +83,9 @@ static const char USAGE[] = "\n"
 " -rev, --reversible\n"
 "        Set the compression to be lossless (reversible in j2c parlance).\n"
 "        Only valid for output j2c images.\n"
+" -f, --filter <name>\n"
+"        Apply the filter <name> to the input images.\n"
+"        Note: so far, only grayscale and sepia are supported.\n"
 " -log, --logmetrics <metric>\n"
 "        Log performance data for <metric>. Results in <metric>.slp\n"
 "        Note: so far, only ImageCompressionTester has been tested.\n"
@@ -350,6 +353,7 @@ int main(int argc, char** argv)
 	int blocks_size = -1;
 	int levels = 0;
 	bool reversible = false;
+    std::string filter_name = "";
 
 	// Init whatever is necessary
 	ll_init_apr();
@@ -523,6 +527,26 @@ int main(int argc, char** argv)
 					break;
 			}
 		}
+		else if (!strcmp(argv[arg], "--filter") || !strcmp(argv[arg], "-f"))
+		{
+			// '--filter' needs to be specified with a named filter argument
+			// Note: for the moment, only sepia and grayscale are supported
+			if ((arg + 1) < argc)
+			{
+				filter_name = argv[arg+1];
+			}
+			if (((arg + 1) >= argc) || (filter_name[0] == '-'))
+			{
+				// We don't have an argument left in the arg list or the next argument is another option
+				std::cout << "No --filter argument given, no filter will be applied" << std::endl;
+			}
+			else
+			{
+				arg += 1;					// Skip that arg now we know it's a valid test name
+				if ((arg + 1) == argc)		// Break out of the loop if we reach the end of the arg list
+					break;
+			}
+		}
 		else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a"))
 		{
 			analyze_performance = true;
@@ -568,6 +592,16 @@ int main(int argc, char** argv)
 			std::cout << "Error: Image " << *in_file << " could not be loaded" << std::endl;
 			continue;
 		}
+        
+        // Apply filter if any
+        if (filter_name == "sepia")
+        {
+            raw_image->filterSepia();
+        }
+        else if (filter_name == "grayscale")
+        {
+            raw_image->filterGrayScale();
+        }
 	
 		// Save file
 		if (out_file != out_end)
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index e5281feff0..73e6f48a8d 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -30,6 +30,8 @@
 
 #include "llmath.h"
 #include "v4coloru.h"
+#include "m3math.h"
+#include "v3math.h"
 
 #include "llimagebmp.h"
 #include "llimagetga.h"
@@ -933,22 +935,42 @@ BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
 	return TRUE ;
 }
 
-// *TODO : Implement real color transform
-// Merov : This is temporary code for testing... 
-void LLImageRaw::colorTransform()
+// Filter Operations
+void LLImageRaw::filterGrayScale()
+{
+    LLMatrix3 gray_scale;
+    LLVector3 luminosity(0.2125, 0.7154, 0.0721);
+    gray_scale.setRows(luminosity, luminosity, luminosity);
+    gray_scale.transpose();
+    colorTransform(gray_scale);
+}
+
+void LLImageRaw::filterSepia()
+{
+    LLMatrix3 sepia;
+    sepia.setRows(LLVector3(0.3588, 0.7044, 0.1368),
+                  LLVector3(0.2990, 0.5870, 0.1140),
+                  LLVector3(0.2392, 0.4696, 0.0912));
+    sepia.transpose();
+    colorTransform(sepia);
+}
+
+// Filter Primitives
+void LLImageRaw::colorTransform(const LLMatrix3 &transform)
 {
 	const S32 components = getComponents();
 	llassert( components >= 1 && components <= 4 );
     
 	S32 pixels = getWidth() * getHeight();
 	U8* dst_data = getData();
-    llinfos << "Merov : Convert the image to Black and White!!! pixels = " << pixels << ", comp = " << components << llendl;
 	for( S32 i=0; i<pixels; i++ )
 	{
-        U8 gray = (U8)(((U32)(dst_data[0]) + (U32)(dst_data[1]) + (U32)(dst_data[2]))/3);
-		dst_data[0] = gray;
-		dst_data[1] = gray;
-		dst_data[2] = gray;
+        LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE]));
+        LLVector3 dst = src * transform;
+        dst.clamp(0.0f,255.0f);
+		dst_data[VRED]   = dst.mV[VRED];
+		dst_data[VGREEN] = dst.mV[VGREEN];
+		dst_data[VBLUE]  = dst.mV[VBLUE];
 		dst_data += components;
 	}
 }
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 96c37f5436..d6b7e65c76 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -71,6 +71,7 @@ const S32 HTTP_PACKET_SIZE = 1496;
 class LLImageFormatted;
 class LLImageRaw;
 class LLColor4U;
+class LLMatrix3;
 class LLPrivateMemoryPool;
 
 typedef enum e_image_codec
@@ -256,8 +257,11 @@ public:
 	// Src and dst are same size.  Src has 4 components.  Dst has 3 components.
 	void compositeUnscaled4onto3( LLImageRaw* src );
     
-    // Filter operations
-    void colorTransform();
+    // Filter Operations
+    void filterGrayScale();
+    void filterSepia();
+    // Filter Primitives
+    void colorTransform(const LLMatrix3 &transform);
 
 protected:
 	// Create an image from a local file (generally used in tools)
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index ab9788a88b..2931178ace 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -589,7 +589,7 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
         // Merov : Filter also the thumbnail?
         if (getFilter() == 1)
         {
-            raw->colorTransform();
+            raw->filterGrayScale();
         }
 		mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
 		mThumbnailUpToDate = TRUE ;
@@ -698,7 +698,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
             // Merov : Time to apply the filter to mPreviewImage!!!
             if (previewp->getFilter() == 1)
             {
-                previewp->mPreviewImage->colorTransform();
+                previewp->mPreviewImage->filterGrayScale();
             }
             
 			// delete any existing image
-- 
cgit v1.2.3


From 08a798bb1d88708765041adf21a784911842f101 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Mon, 30 Dec 2013 20:33:33 -0800
Subject: ACME-1236 : WIP : Implement saturation/desaturation transform filter,
 add it to llimage_libtest for testing

---
 .../llimage_libtest/llimage_libtest.cpp            |  4 +++
 indra/llimage/llimage.cpp                          | 31 ++++++++++++++++++++++
 indra/llimage/llimage.h                            |  1 +
 3 files changed, 36 insertions(+)

diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index e485136f58..cbd6ccebbf 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -602,6 +602,10 @@ int main(int argc, char** argv)
         {
             raw_image->filterGrayScale();
         }
+        else if (filter_name == "saturate")
+        {
+            raw_image->filterSaturate(2.0f);
+        }
 	
 		// Save file
 		if (out_file != out_end)
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 73e6f48a8d..4028514898 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -955,6 +955,37 @@ void LLImageRaw::filterSepia()
     colorTransform(sepia);
 }
 
+void LLImageRaw::filterSaturate(F32 saturation)
+{
+    // Matrix to Lij
+    LLMatrix3 r_a;
+    LLMatrix3 r_b;
+
+    // 45 degre rotation around z
+    r_a.setRows(LLVector3(0.7071,  0.7071, 0.0),
+                LLVector3(-0.7071,  0.7071, 0.0),
+                LLVector3(0.0,     0.0,    1.0));
+    // 54.73 degre rotation around y
+    r_b.setRows(LLVector3(0.5773,  0.0, -0.8165),
+                LLVector3(0.0,     1.0,  0.0),
+                LLVector3(0.8165,  0.0,  0.5773));
+
+    // Coordinate conversion
+    LLMatrix3 Lij = r_b * r_a;
+    LLMatrix3 Lij_inv = Lij;
+    Lij_inv.transpose();
+    
+    // Local saturation transform
+    LLMatrix3 s;
+    s.setRows(LLVector3(saturation, 0.0,  0.0),
+              LLVector3(0.0,  saturation, 0.0),
+              LLVector3(0.0,        0.0,  1.0));
+
+    // Global saturation transform
+    LLMatrix3 transfo = Lij_inv * s * Lij;
+    colorTransform(transfo);
+}
+
 // Filter Primitives
 void LLImageRaw::colorTransform(const LLMatrix3 &transform)
 {
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index d6b7e65c76..1742cf8a71 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -260,6 +260,7 @@ public:
     // Filter Operations
     void filterGrayScale();
     void filterSepia();
+    void filterSaturate(F32 s);
     // Filter Primitives
     void colorTransform(const LLMatrix3 &transform);
 
-- 
cgit v1.2.3


From 218d305c443d4e5ddba03c6f4a988924939d805d Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 1 Jan 2014 17:13:06 -0800
Subject: ACME-1236 : WIP : add an optional filter parameter to llimage_libtest

---
 .../llimage_libtest/llimage_libtest.cpp            | 23 ++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index cbd6ccebbf..d1535bf3cf 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -83,9 +83,10 @@ static const char USAGE[] = "\n"
 " -rev, --reversible\n"
 "        Set the compression to be lossless (reversible in j2c parlance).\n"
 "        Only valid for output j2c images.\n"
-" -f, --filter <name>\n"
-"        Apply the filter <name> to the input images.\n"
-"        Note: so far, only grayscale and sepia are supported.\n"
+" -f, --filter <name> [<param>]\n"
+"        Apply the filter <name> to the input images using the optional param (float) value.\n"
+"        Notes: - 'grayscale' and 'sepia' are supported (no param).\n"
+"               - 'saturate' uses the param: param < 1.0 will desaturate the colors, param > 1.0 will saturate them.\n"
 " -log, --logmetrics <metric>\n"
 "        Log performance data for <metric>. Results in <metric>.slp\n"
 "        Note: so far, only ImageCompressionTester has been tested.\n"
@@ -354,6 +355,7 @@ int main(int argc, char** argv)
 	int levels = 0;
 	bool reversible = false;
     std::string filter_name = "";
+    double filter_param = 0.0;
 
 	// Init whatever is necessary
 	ll_init_apr();
@@ -530,7 +532,6 @@ int main(int argc, char** argv)
 		else if (!strcmp(argv[arg], "--filter") || !strcmp(argv[arg], "-f"))
 		{
 			// '--filter' needs to be specified with a named filter argument
-			// Note: for the moment, only sepia and grayscale are supported
 			if ((arg + 1) < argc)
 			{
 				filter_name = argv[arg+1];
@@ -545,7 +546,17 @@ int main(int argc, char** argv)
 				arg += 1;					// Skip that arg now we know it's a valid test name
 				if ((arg + 1) == argc)		// Break out of the loop if we reach the end of the arg list
 					break;
-			}
+                // --filter can also have an optional parameter
+                std::string value_str;
+                value_str = argv[arg+1];    // Check the next arg
+                if (value_str[0] != '-')    // If it's not another argument, it's a filter parameter value
+                {
+                    filter_param = atof(value_str.c_str());
+                    arg += 1;					// Skip that arg now we used it as a valid filter param
+                    if ((arg + 1) == argc)		// Break out of the loop if we reach the end of the arg list
+                        break;
+               }
+            }
 		}
 		else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a"))
 		{
@@ -604,7 +615,7 @@ int main(int argc, char** argv)
         }
         else if (filter_name == "saturate")
         {
-            raw_image->filterSaturate(2.0f);
+            raw_image->filterSaturate((float)(filter_param));
         }
 	
 		// Save file
-- 
cgit v1.2.3


From 9dca514c0b416c1b15e9a63e6f5af1b52df70b7e Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 1 Jan 2014 17:58:52 -0800
Subject: ACME-1236 : WIP : add filterRotate to rotate hue, add rotate as a
 valid argument to --filter in llimage_libtest

---
 .../llimage_libtest/llimage_libtest.cpp            | 11 +++--
 indra/llimage/llimage.cpp                          | 48 +++++++++++++++++++---
 indra/llimage/llimage.h                            |  3 +-
 3 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index d1535bf3cf..1f9a5f0e18 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -84,9 +84,10 @@ static const char USAGE[] = "\n"
 "        Set the compression to be lossless (reversible in j2c parlance).\n"
 "        Only valid for output j2c images.\n"
 " -f, --filter <name> [<param>]\n"
-"        Apply the filter <name> to the input images using the optional param (float) value.\n"
-"        Notes: - 'grayscale' and 'sepia' are supported (no param).\n"
-"               - 'saturate' uses the param: param < 1.0 will desaturate the colors, param > 1.0 will saturate them.\n"
+"        Apply the filter <name> to the input images using the optional param (float) value:\n"
+"        - 'grayscale' and 'sepia' just do that (no param).\n"
+"        - 'saturate' changes color saturation according to param: param < 1.0 will desaturate, param > 1.0 will saturate.\n"
+"        - 'rotate' rotates the color hue according to param (in degree, positive value only).\n"
 " -log, --logmetrics <metric>\n"
 "        Log performance data for <metric>. Results in <metric>.slp\n"
 "        Note: so far, only ImageCompressionTester has been tested.\n"
@@ -617,6 +618,10 @@ int main(int argc, char** argv)
         {
             raw_image->filterSaturate((float)(filter_param));
         }
+        else if (filter_name == "rotate")
+        {
+            raw_image->filterRotate((float)(filter_param));
+        }
 	
 		// Save file
 		if (out_file != out_end)
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 4028514898..8b7c352437 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -962,13 +962,15 @@ void LLImageRaw::filterSaturate(F32 saturation)
     LLMatrix3 r_b;
 
     // 45 degre rotation around z
-    r_a.setRows(LLVector3(0.7071,  0.7071, 0.0),
-                LLVector3(-0.7071,  0.7071, 0.0),
-                LLVector3(0.0,     0.0,    1.0));
+    r_a.setRows(LLVector3( OO_SQRT2,  OO_SQRT2, 0.0),
+                LLVector3(-OO_SQRT2,  OO_SQRT2, 0.0),
+                LLVector3( 0.0,       0.0,      1.0));
     // 54.73 degre rotation around y
-    r_b.setRows(LLVector3(0.5773,  0.0, -0.8165),
-                LLVector3(0.0,     1.0,  0.0),
-                LLVector3(0.8165,  0.0,  0.5773));
+    float oo_sqrt3 = 1.0f / F_SQRT3;
+    float sin_54 = F_SQRT2 * oo_sqrt3;
+    r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54),
+                LLVector3(0.0,      1.0,  0.0),
+                LLVector3(sin_54,   0.0,  oo_sqrt3));
 
     // Coordinate conversion
     LLMatrix3 Lij = r_b * r_a;
@@ -986,6 +988,40 @@ void LLImageRaw::filterSaturate(F32 saturation)
     colorTransform(transfo);
 }
 
+void LLImageRaw::filterRotate(F32 alpha)
+{
+    // Matrix to Lij
+    LLMatrix3 r_a;
+    LLMatrix3 r_b;
+    
+    // 45 degre rotation around z
+    r_a.setRows(LLVector3( OO_SQRT2,  OO_SQRT2, 0.0),
+                LLVector3(-OO_SQRT2,  OO_SQRT2, 0.0),
+                LLVector3( 0.0,       0.0,      1.0));
+    // 54.73 degre rotation around y
+    float oo_sqrt3 = 1.0f / F_SQRT3;
+    float sin_54 = F_SQRT2 * oo_sqrt3;
+    r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54),
+                LLVector3(0.0,      1.0,  0.0),
+                LLVector3(sin_54,   0.0,  oo_sqrt3));
+    
+    // Coordinate conversion
+    LLMatrix3 Lij = r_b * r_a;
+    LLMatrix3 Lij_inv = Lij;
+    Lij_inv.transpose();
+    
+    // Local color rotation transform
+    LLMatrix3 r;
+    alpha *= DEG_TO_RAD;
+    r.setRows(LLVector3( cosf(alpha), sinf(alpha), 0.0),
+              LLVector3(-sinf(alpha), cosf(alpha), 0.0),
+              LLVector3( 0.0,         0.0,         1.0));
+    
+    // Global color rotation transform
+    LLMatrix3 transfo = Lij_inv * r * Lij;
+    colorTransform(transfo);
+}
+
 // Filter Primitives
 void LLImageRaw::colorTransform(const LLMatrix3 &transform)
 {
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 1742cf8a71..3a9c088dbd 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -260,7 +260,8 @@ public:
     // Filter Operations
     void filterGrayScale();
     void filterSepia();
-    void filterSaturate(F32 s);
+    void filterSaturate(F32 saturation);    // < 1.0 desaturates, > 1.0 saturates
+    void filterRotate(F32 alpha);           // rotates hue, alpha in degrees
     // Filter Primitives
     void colorTransform(const LLMatrix3 &transform);
 
-- 
cgit v1.2.3


From 205a4e3dc63c338c05e27a4806cdfd6f50bac2b6 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 1 Jan 2014 19:42:10 -0800
Subject: ACME-1236 : WIP : add filterGamma, computeHistograms, colorCorrect,
 implemented filter gamma to llimage_libtest for testing

---
 .../llimage_libtest/llimage_libtest.cpp            |  4 +
 indra/llimage/llimage.cpp                          | 92 +++++++++++++++++++++-
 indra/llimage/llimage.h                            | 11 +++
 3 files changed, 103 insertions(+), 4 deletions(-)

diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 1f9a5f0e18..afd5e2ce98 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -622,6 +622,10 @@ int main(int argc, char** argv)
         {
             raw_image->filterRotate((float)(filter_param));
         }
+        else if (filter_name == "gamma")
+        {
+            raw_image->filterGamma((float)(filter_param));
+        }
 	
 		// Save file
 		if (out_file != out_end)
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 8b7c352437..d406995f3a 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -97,7 +97,11 @@ LLImageBase::LLImageBase()
 	  mHeight(0),
 	  mComponents(0),
 	  mBadBufferAllocation(false),
-	  mAllowOverSize(false)
+	  mAllowOverSize(false),
+      mHistoRed(NULL),
+      mHistoGreen(NULL),
+      mHistoBlue(NULL),
+      mHistoBrightness(NULL)
 {
 }
 
@@ -105,10 +109,14 @@ LLImageBase::LLImageBase()
 LLImageBase::~LLImageBase()
 {
 	deleteData(); // virtual
+    ll_aligned_free_16(mHistoRed);
+    ll_aligned_free_16(mHistoGreen);
+    ll_aligned_free_16(mHistoBlue);
+    ll_aligned_free_16(mHistoBrightness);
 }
 
-//static 
-void LLImageBase::createPrivatePool() 
+//static
+void LLImageBase::createPrivatePool()
 {
 	if(!sPrivatePoolp)
 	{
@@ -1022,6 +1030,18 @@ void LLImageRaw::filterRotate(F32 alpha)
     colorTransform(transfo);
 }
 
+void LLImageRaw::filterGamma(F32 gamma)
+{
+    U8 gamma_lut[256];
+    
+    for (S32 i = 0; i < 256; i++)
+    {
+        gamma_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma)))));
+    }
+    
+    colorCorrect(gamma_lut,gamma_lut,gamma_lut);
+}
+
 // Filter Primitives
 void LLImageRaw::colorTransform(const LLMatrix3 &transform)
 {
@@ -1030,7 +1050,7 @@ void LLImageRaw::colorTransform(const LLMatrix3 &transform)
     
 	S32 pixels = getWidth() * getHeight();
 	U8* dst_data = getData();
-	for( S32 i=0; i<pixels; i++ )
+	for (S32 i = 0; i < pixels; i++)
 	{
         LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE]));
         LLVector3 dst = src * transform;
@@ -1042,6 +1062,70 @@ void LLImageRaw::colorTransform(const LLMatrix3 &transform)
 	}
 }
 
+void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue)
+{
+	const S32 components = getComponents();
+	llassert( components >= 1 && components <= 4 );
+    
+	S32 pixels = getWidth() * getHeight();
+	U8* dst_data = getData();
+	for (S32 i = 0; i < pixels; i++)
+	{
+		dst_data[VRED]   = lut_red[dst_data[VRED]];
+		dst_data[VGREEN] = lut_green[dst_data[VGREEN]];
+		dst_data[VBLUE]  = lut_blue[dst_data[VBLUE]];
+		dst_data += components;
+	}
+}
+
+void LLImageRaw::computeHistograms()
+{
+ 	const S32 components = getComponents();
+	llassert( components >= 1 && components <= 4 );
+    
+    // Allocate memory for the histograms
+    if (!mHistoRed)
+    {
+        mHistoRed = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
+    }
+    if (!mHistoGreen)
+    {
+        mHistoGreen = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
+    }
+    if (!mHistoBlue)
+    {
+        mHistoBlue = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
+    }
+    if (!mHistoBrightness)
+    {
+        mHistoBrightness = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
+    }
+    
+    // Initialize them
+    for (S32 i = 0; i < 256; i++)
+    {
+        mHistoRed[i] = 0;
+        mHistoGreen[i] = 0;
+        mHistoBlue[i] = 0;
+        mHistoBrightness[i] = 0;
+    }
+    
+    // Compute them
+	S32 pixels = getWidth() * getHeight();
+	U8* dst_data = getData();
+	for (S32 i = 0; i < pixels; i++)
+	{
+        mHistoRed[dst_data[VRED]]++;
+        mHistoGreen[dst_data[VGREEN]]++;
+        mHistoBlue[dst_data[VBLUE]]++;
+        // Note: this is a very simple shorthand for brightness but it's OK for our use
+        S32 brightness = ((S32)(dst_data[VRED]) + (S32)(dst_data[VGREEN]) + (S32)(dst_data[VBLUE])) / 3;
+        mHistoBrightness[brightness]++;
+        // next pixel...
+		dst_data += components;
+	}
+}
+
 void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step )
 {
 	const S32 components = getComponents();
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 3a9c088dbd..89734693cc 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -151,6 +151,12 @@ protected:
 	// special accessor to allow direct setting of mData and mDataSize by LLImageFormatted
 	void setDataAndSize(U8 *data, S32 size);
 	
+    // Histograms (if we ever happen to need them)
+    U32 *mHistoRed;
+    U32 *mHistoGreen;
+    U32 *mHistoBlue;
+    U32 *mHistoBrightness;
+    
 public:
 	static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels);
 	
@@ -262,8 +268,11 @@ public:
     void filterSepia();
     void filterSaturate(F32 saturation);    // < 1.0 desaturates, > 1.0 saturates
     void filterRotate(F32 alpha);           // rotates hue, alpha in degrees
+    void filterGamma(F32 gamma);            // Apply a gamma lookup to all channels
+    
     // Filter Primitives
     void colorTransform(const LLMatrix3 &transform);
+    void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue);
 
 protected:
 	// Create an image from a local file (generally used in tools)
@@ -276,6 +285,8 @@ protected:
 
 	void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ;
 
+    void computeHistograms();
+
 public:
 	static S32 sGlobalRawMemory;
 	static S32 sRawImageCount;
-- 
cgit v1.2.3


From d28b92744ee0d4a19a5587585998e5c351f6d300 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Thu, 2 Jan 2014 16:14:38 -0800
Subject: ACME-1236 : WIP : added all the color correction filters: colorize,
 linarize, equalize, contrast, brightness

---
 .../llimage_libtest/CMakeLists.txt                 |   3 +
 .../llimage_libtest/llimage_libtest.cpp            |  44 +++++-
 indra/llimage/llimage.cpp                          | 155 +++++++++++++++++++++
 indra/llimage/llimage.h                            |  16 ++-
 4 files changed, 209 insertions(+), 9 deletions(-)

diff --git a/indra/integration_tests/llimage_libtest/CMakeLists.txt b/indra/integration_tests/llimage_libtest/CMakeLists.txt
index 36a7d38bb7..8a83ac498f 100755
--- a/indra/integration_tests/llimage_libtest/CMakeLists.txt
+++ b/indra/integration_tests/llimage_libtest/CMakeLists.txt
@@ -7,6 +7,7 @@ project (llimage_libtest)
 include(00-Common)
 include(LLCommon)
 include(LLImage)
+include(LLMath)
 include(LLImageJ2COJ) 
 include(LLKDU)
 include(LLVFS)
@@ -15,6 +16,7 @@ include_directories(
     ${LLCOMMON_INCLUDE_DIRS}
     ${LLVFS_INCLUDE_DIRS}
     ${LLIMAGE_INCLUDE_DIRS}
+    ${LLMATH_INCLUDE_DIRS}
     )
 include_directories(SYSTEM
     ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
@@ -64,6 +66,7 @@ endif (DARWIN)
 target_link_libraries(llimage_libtest
     ${LLCOMMON_LIBRARIES}
     ${LLVFS_LIBRARIES}
+    ${LLMATH_LIBRARIES}
     ${LLIMAGE_LIBRARIES}
     ${LLKDU_LIBRARIES}
     ${KDU_LIBRARY}
diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index afd5e2ce98..4d32282a0d 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -39,6 +39,7 @@
 #include "llimagej2c.h"
 #include "lldir.h"
 #include "lldiriterator.h"
+#include "v4coloru.h"
 
 // system libraries
 #include <iostream>
@@ -84,10 +85,18 @@ static const char USAGE[] = "\n"
 "        Set the compression to be lossless (reversible in j2c parlance).\n"
 "        Only valid for output j2c images.\n"
 " -f, --filter <name> [<param>]\n"
-"        Apply the filter <name> to the input images using the optional param (float) value:\n"
-"        - 'grayscale' and 'sepia' just do that (no param).\n"
-"        - 'saturate' changes color saturation according to param: param < 1.0 will desaturate, param > 1.0 will saturate.\n"
-"        - 'rotate' rotates the color hue according to param (in degree, positive value only).\n"
+"        Apply the filter <name> to the input images using the optional <param> value. Admissible names:\n"
+"        - 'grayscale' converts to grayscale (no param).\n"
+"        - 'sepia' converts to sepia (no param).\n"
+"        - 'saturate' changes color saturation according to <param>: < 1.0 will desaturate, > 1.0 will saturate.\n"
+"        - 'rotate' rotates the color hue according to <param> (in degree, positive value only).\n"
+"        - 'gamma' applies gamma curve <param> to all channels: > 1.0 will darken, < 1.0 will lighten.\n"
+"        - 'colorize' applies a red tint to the image using <param> as an alpha (transparency between 0.0 and 1.0) value.\n"
+"        - 'contrast' modifies the contrast according to <param> : > 1.0 will enhance the contrast, <1.0 will flatten it.\n"
+"        - 'brighten' adds <param> light to the image (<param> between 0 and 255).\n"
+"        - 'darken' substracts <param> light to the image (<param> between 0 and 255).\n"
+"        - 'linearize' optimizes the contrast using the brightness histogram. <param> is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n"
+"        - 'posterize' redistributes the colors between <param> classes per channel (<param> between 2 and 255).\n"
 " -log, --logmetrics <metric>\n"
 "        Log performance data for <metric>. Results in <metric>.slp\n"
 "        Note: so far, only ImageCompressionTester has been tested.\n"
@@ -626,6 +635,33 @@ int main(int argc, char** argv)
         {
             raw_image->filterGamma((float)(filter_param));
         }
+        else if (filter_name == "colorize")
+        {
+            // For testing, we just colorize in red, modulate by the alpha passed as a parameter
+            LLColor4U color = LLColor4U::red;
+            color.setAlpha((U8)(filter_param * 255.0));
+            raw_image->filterColorize(color);
+        }
+        else if (filter_name == "contrast")
+        {
+            raw_image->filterContrast((float)(filter_param));
+        }
+        else if (filter_name == "brighten")
+        {
+            raw_image->filterBrightness((S32)(filter_param));
+        }
+        else if (filter_name == "darken")
+        {
+            raw_image->filterBrightness((S32)(-filter_param));
+        }
+        else if (filter_name == "linearize")
+        {
+            raw_image->filterLinearize((float)(filter_param));
+        }
+        else if (filter_name == "posterize")
+        {
+            raw_image->filterEqualize((S32)(filter_param));
+        }
 	
 		// Save file
 		if (out_file != out_end)
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index d406995f3a..5dc9c24f6c 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -1042,6 +1042,152 @@ void LLImageRaw::filterGamma(F32 gamma)
     colorCorrect(gamma_lut,gamma_lut,gamma_lut);
 }
 
+void LLImageRaw::filterLinearize(F32 tail)
+{
+    // Get the histogram
+    U32* histo = getBrightnessHistogram();
+    
+    // Compute cumulated histogram
+    U32 cumulated_histo[256];
+    cumulated_histo[0] = histo[0];
+    for (S32 i = 1; i < 256; i++)
+    {
+        cumulated_histo[i] = cumulated_histo[i-1] + histo[i];
+    }
+    
+    // Compute min and max counts minus tail
+    tail = llclampf(tail);
+    S32 total = cumulated_histo[255];
+    S32 min_c = (S32)((F32)(total) * tail);
+    S32 max_c = (S32)((F32)(total) * (1.0 - tail));
+    
+    // Find min and max values
+    S32 min_v = 0;
+    while (cumulated_histo[min_v] < min_c)
+    {
+        min_v++;
+    }
+    S32 max_v = 255;
+    while (cumulated_histo[max_v] > max_c)
+    {
+        max_v--;
+    }
+    
+    // Compute linear lookup table
+    U8 linear_lut[256];
+    if (max_v == min_v)
+    {
+        // Degenerated binary split case
+        for (S32 i = 0; i < 256; i++)
+        {
+            linear_lut[i] = (i < min_v ? 0 : 255);
+        }
+    }
+    else
+    {
+        // Linearize between min and max
+        F32 slope = 255.0 / (F32)(max_v - min_v);
+        F32 translate = -min_v * slope;
+        for (S32 i = 0; i < 256; i++)
+        {
+            linear_lut[i] = (U8)(llclampb((S32)(slope*i + translate)));
+        }
+    }
+    
+    // Apply lookup table
+    colorCorrect(linear_lut,linear_lut,linear_lut);    
+}
+
+void LLImageRaw::filterEqualize(S32 nb_classes)
+{
+    // Regularize the parameter: must be between 2 and 255
+    nb_classes = llmax(nb_classes,2);
+    nb_classes = llclampb(nb_classes);
+    
+    // Get the histogram
+    U32* histo = getBrightnessHistogram();
+    
+    // Compute cumulated histogram
+    U32 cumulated_histo[256];
+    cumulated_histo[0] = histo[0];
+    for (S32 i = 1; i < 256; i++)
+    {
+        cumulated_histo[i] = cumulated_histo[i-1] + histo[i];
+    }
+    
+    // Compute deltas
+    S32 total = cumulated_histo[255];
+    S32 delta_count = total / nb_classes;
+    S32 current_count = delta_count;
+    S32 delta_value = 256 / (nb_classes - 1);
+    S32 current_value = 0;
+    
+    // Compute equalized lookup table
+    U8 equalize_lut[256];
+    for (S32 i = 0; i < 256; i++)
+    {
+        equalize_lut[i] = (U8)(current_value);
+        if (cumulated_histo[i] >= current_count)
+        {
+            current_count += delta_count;
+            current_value += delta_value;
+            current_value = llclampb(current_value);
+        }
+    }
+
+    // Apply lookup table
+    colorCorrect(equalize_lut,equalize_lut,equalize_lut);
+}
+
+void LLImageRaw::filterColorize(const LLColor4U& color)
+{
+    U8 red_lut[256];
+    U8 green_lut[256];
+    U8 blue_lut[256];
+    
+    F32 alpha = (F32)(color.mV[3])/255.0;
+    F32 inv_alpha = 1.0 - alpha;
+    
+    F32 red_composite   =  alpha * (F32)(color.mV[0]);
+    F32 green_composite =  alpha * (F32)(color.mV[1]);
+    F32 blue_composite  =  alpha * (F32)(color.mV[2]);
+    
+    for (S32 i = 0; i < 256; i++)
+    {
+        red_lut[i]   = (U8)(llclampb((S32)(inv_alpha*(F32)(i) + red_composite)));
+        green_lut[i] = (U8)(llclampb((S32)(inv_alpha*(F32)(i) + green_composite)));
+        blue_lut[i]  = (U8)(llclampb((S32)(inv_alpha*(F32)(i) + blue_composite)));
+    }
+    
+    colorCorrect(red_lut,green_lut,blue_lut);
+}
+
+void LLImageRaw::filterContrast(F32 slope)
+{
+    U8 contrast_lut[256];
+    
+    F32 translate = 128.0 * (1.0 - slope);
+    
+    for (S32 i = 0; i < 256; i++)
+    {
+        contrast_lut[i] = (U8)(llclampb((S32)(slope*i + translate)));
+    }
+    
+    colorCorrect(contrast_lut,contrast_lut,contrast_lut);
+}
+
+void LLImageRaw::filterBrightness(S32 add)
+{
+    U8 brightness_lut[256];
+    
+    for (S32 i = 0; i < 256; i++)
+    {
+        brightness_lut[i] = (U8)(llclampb((S32)((S32)(i) + add)));
+    }
+    
+    colorCorrect(brightness_lut,brightness_lut,brightness_lut);
+}
+
 // Filter Primitives
 void LLImageRaw::colorTransform(const LLMatrix3 &transform)
 {
@@ -1078,6 +1224,15 @@ void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8*
 	}
 }
 
+U32* LLImageRaw::getBrightnessHistogram()
+{
+    if (!mHistoBrightness)
+    {
+        computeHistograms();
+    }
+    return mHistoBrightness;
+}
+
 void LLImageRaw::computeHistograms()
 {
  	const S32 components = getComponents();
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 89734693cc..b62deadee0 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -264,15 +264,21 @@ public:
 	void compositeUnscaled4onto3( LLImageRaw* src );
     
     // Filter Operations
-    void filterGrayScale();
-    void filterSepia();
-    void filterSaturate(F32 saturation);    // < 1.0 desaturates, > 1.0 saturates
-    void filterRotate(F32 alpha);           // rotates hue, alpha in degrees
-    void filterGamma(F32 gamma);            // Apply a gamma lookup to all channels
+    void filterGrayScale();                         // Convert to grayscale
+    void filterSepia();                             // Convert to sepia
+    void filterSaturate(F32 saturation);            // < 1.0 desaturates, > 1.0 saturates
+    void filterRotate(F32 alpha);                   // Rotates hue according to alpha, alpha in degrees
+    void filterGamma(F32 gamma);                    // Apply gamma to all channels
+    void filterLinearize(F32 tail);                 // Use histogram to linearize constrast between min and max values minus tail
+    void filterEqualize(S32 nb_classes);            // Use histogram to equalize constrast throughout the image
+    void filterColorize(const LLColor4U& color);    // Colorize with color. Alpha will be taken into account for colorization intensity.
+    void filterContrast(F32 slope);                 // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast
+    void filterBrightness(S32 add);                 // Change brightness according to add: > 0 brighter, < 0 darker
     
     // Filter Primitives
     void colorTransform(const LLMatrix3 &transform);
     void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue);
+    U32* getBrightnessHistogram();
 
 protected:
 	// Create an image from a local file (generally used in tools)
-- 
cgit v1.2.3


From 1b5fb662927ac84606cf767c8c9ec350e82b656f Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Fri, 3 Jan 2014 14:19:29 -0800
Subject: ACME-1236 : WIP : Added the vignette mode. Can be applied to
 colorCorrect and color Transform. Added new -v argument to llimage_libtest

---
 .../llimage_libtest/llimage_libtest.cpp            |  47 ++++++++-
 indra/llimage/llimage.cpp                          | 106 +++++++++++++++++----
 indra/llimage/llimage.h                            |  16 ++++
 3 files changed, 152 insertions(+), 17 deletions(-)

diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 4d32282a0d..45e60f64e6 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -97,6 +97,10 @@ static const char USAGE[] = "\n"
 "        - 'darken' substracts <param> light to the image (<param> between 0 and 255).\n"
 "        - 'linearize' optimizes the contrast using the brightness histogram. <param> is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n"
 "        - 'posterize' redistributes the colors between <param> classes per channel (<param> between 2 and 255).\n"
+" -v, --vignette <name> [<feather>]\n"
+"        Apply a circular central vignette <name> to the filter using the optional <feather> value. Admissible names:\n"
+"        - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n"
+"        - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n"
 " -log, --logmetrics <metric>\n"
 "        Log performance data for <metric>. Results in <metric>.slp\n"
 "        Note: so far, only ImageCompressionTester has been tested.\n"
@@ -366,6 +370,8 @@ int main(int argc, char** argv)
 	bool reversible = false;
     std::string filter_name = "";
     double filter_param = 0.0;
+    std::string vignette_name = "";
+    double vignette_param = 1.0;
 
 	// Init whatever is necessary
 	ll_init_apr();
@@ -568,7 +574,36 @@ int main(int argc, char** argv)
                }
             }
 		}
-		else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a"))
+		else if (!strcmp(argv[arg], "--vignette") || !strcmp(argv[arg], "-v"))
+		{
+			// '--vignette' needs to be specified with a named vignette argument
+			if ((arg + 1) < argc)
+			{
+				vignette_name = argv[arg+1];
+			}
+			if (((arg + 1) >= argc) || (vignette_name[0] == '-'))
+			{
+				// We don't have an argument left in the arg list or the next argument is another option
+				std::cout << "No --vignette argument given, no vignette will be applied to filters" << std::endl;
+			}
+			else
+			{
+				arg += 1;					// Skip that arg now we know it's a valid vignette name
+				if ((arg + 1) == argc)		// Break out of the loop if we reach the end of the arg list
+					break;
+                // --vignette can also have an optional parameter
+                std::string value_str;
+                value_str = argv[arg+1];    // Check the next arg
+                if (value_str[0] != '-')    // If it's not another argument, it's a vignette parameter value
+                {
+                    vignette_param = atof(value_str.c_str());
+                    arg += 1;					// Skip that arg now we used it as a valid vignette param
+                    if ((arg + 1) == argc)		// Break out of the loop if we reach the end of the arg list
+                        break;
+                }
+            }
+		}
+        else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a"))
 		{
 			analyze_performance = true;
 		}
@@ -614,6 +649,16 @@ int main(int argc, char** argv)
 			continue;
 		}
         
+        // Set the vignette if any
+        if (vignette_name == "blend")
+        {
+            raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(vignette_param));
+        }
+        else if (vignette_name == "fade")
+        {
+            raw_image->setVignette(VIGNETTE_MODE_FADE,(float)(vignette_param));
+        }
+        
         // Apply filter if any
         if (filter_name == "sepia")
         {
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 5dc9c24f6c..da22ed5e5b 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -101,7 +101,9 @@ LLImageBase::LLImageBase()
       mHistoRed(NULL),
       mHistoGreen(NULL),
       mHistoBlue(NULL),
-      mHistoBrightness(NULL)
+      mHistoBrightness(NULL),
+      mVignetteMode(VIGNETTE_MODE_NONE),
+      mVignetteGamma(1.0)
 {
 }
 
@@ -1194,17 +1196,44 @@ void LLImageRaw::colorTransform(const LLMatrix3 &transform)
 	const S32 components = getComponents();
 	llassert( components >= 1 && components <= 4 );
     
-	S32 pixels = getWidth() * getHeight();
+	S32 width  = getWidth();
+    S32 height = getHeight();
+    
 	U8* dst_data = getData();
-	for (S32 i = 0; i < pixels; i++)
+	for (S32 j = 0; j < height; j++)
 	{
-        LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE]));
-        LLVector3 dst = src * transform;
-        dst.clamp(0.0f,255.0f);
-		dst_data[VRED]   = dst.mV[VRED];
-		dst_data[VGREEN] = dst.mV[VGREEN];
-		dst_data[VBLUE]  = dst.mV[VBLUE];
-		dst_data += components;
+        for (S32 i = 0; i < width; i++)
+        {
+            LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE]));
+            LLVector3 dst = src * transform;
+            dst.clamp(0.0f,255.0f);
+            if (mVignetteMode == VIGNETTE_MODE_NONE)
+            {
+                dst_data[VRED]   = dst.mV[VRED];
+                dst_data[VGREEN] = dst.mV[VGREEN];
+                dst_data[VBLUE]  = dst.mV[VBLUE];
+            }
+            else
+            {
+                F32 alpha = getVignetteAlpha(i,j);
+                if (mVignetteMode == VIGNETTE_MODE_BLEND)
+                {
+                    // Blends with the source image on the edges
+                    F32 inv_alpha = 1.0 - alpha;
+                    dst_data[VRED]   = inv_alpha * src.mV[VRED]   + alpha * dst.mV[VRED];
+                    dst_data[VGREEN] = inv_alpha * src.mV[VGREEN] + alpha * dst.mV[VGREEN];
+                    dst_data[VBLUE]  = inv_alpha * src.mV[VBLUE]  + alpha * dst.mV[VBLUE];
+                }
+                else // VIGNETTE_MODE_FADE
+                {
+                    // Fade to black on the edges
+                    dst_data[VRED]   = alpha * dst.mV[VRED];
+                    dst_data[VGREEN] = alpha * dst.mV[VGREEN];
+                    dst_data[VBLUE]  = alpha * dst.mV[VBLUE];
+                }
+            }
+            dst_data += components;
+        }
 	}
 }
 
@@ -1213,17 +1242,62 @@ void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8*
 	const S32 components = getComponents();
 	llassert( components >= 1 && components <= 4 );
     
-	S32 pixels = getWidth() * getHeight();
+	S32 width  = getWidth();
+    S32 height = getHeight();
+    
 	U8* dst_data = getData();
-	for (S32 i = 0; i < pixels; i++)
+	for (S32 j = 0; j < height; j++)
 	{
-		dst_data[VRED]   = lut_red[dst_data[VRED]];
-		dst_data[VGREEN] = lut_green[dst_data[VGREEN]];
-		dst_data[VBLUE]  = lut_blue[dst_data[VBLUE]];
-		dst_data += components;
+        for (S32 i = 0; i < width; i++)
+        {
+            if (mVignetteMode == VIGNETTE_MODE_NONE)
+            {
+                dst_data[VRED]   = lut_red[dst_data[VRED]];
+                dst_data[VGREEN] = lut_green[dst_data[VGREEN]];
+                dst_data[VBLUE]  = lut_blue[dst_data[VBLUE]];
+            }
+            else
+            {
+                F32 alpha = getVignetteAlpha(i,j);
+                if (mVignetteMode == VIGNETTE_MODE_BLEND)
+                {
+                    // Blends with the source image on the edges
+                    F32 inv_alpha = 1.0 - alpha;
+                    dst_data[VRED]   = inv_alpha * dst_data[VRED]  + alpha * lut_red[dst_data[VRED]];
+                    dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * lut_green[dst_data[VGREEN]];
+                    dst_data[VBLUE]  = inv_alpha * dst_data[VBLUE]  + alpha * lut_blue[dst_data[VBLUE]];
+                }
+                else // VIGNETTE_MODE_FADE
+                {
+                    // Fade to black on the edges
+                    dst_data[VRED]   = alpha * lut_red[dst_data[VRED]];
+                    dst_data[VGREEN] = alpha * lut_green[dst_data[VGREEN]];
+                    dst_data[VBLUE]  = alpha * lut_blue[dst_data[VBLUE]];
+                }
+            }
+            dst_data += components;
+        }
 	}
 }
 
+void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma)
+{
+    mVignetteMode = mode;
+    mVignetteGamma = gamma;
+    // We always center the vignette on the image and fits it in the image smallest dimension
+    mVignetteCenterX = getWidth()/2;
+    mVignetteCenterY = getHeight()/2;
+    mVignetteWidth = llmin(getWidth()/2,getHeight()/2);
+}
+
+F32 LLImageRaw::getVignetteAlpha(S32 i, S32 j)
+{
+    // alpha is a modified gaussian value, with a center and fading in a circular pattern toward the edges
+    // the gamma parameter controls the intensity of the drop down from alpha 1.0 to 0.0
+    F32 d_center_square = (i - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY);
+    return powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f));
+}
+
 U32* LLImageRaw::getBrightnessHistogram()
 {
     if (!mHistoBrightness)
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index b62deadee0..b9f6a12bdd 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -87,6 +87,13 @@ typedef enum e_image_codec
 	IMG_CODEC_EOF  = 8
 } EImageCodec;
 
+typedef enum e_vignette_mode
+{
+	VIGNETTE_MODE_NONE  = 0,
+	VIGNETTE_MODE_BLEND = 1,
+	VIGNETTE_MODE_FADE  = 2
+} EVignetteMode;
+
 //============================================================================
 // library initialization class
 
@@ -157,6 +164,13 @@ protected:
     U32 *mHistoBlue;
     U32 *mHistoBrightness;
     
+    // Vignette filtering
+    EVignetteMode mVignetteMode;
+    S32 mVignetteCenterX;
+    S32 mVignetteCenterY;
+    S32 mVignetteWidth;
+    F32 mVignetteGamma;
+    
 public:
 	static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels);
 	
@@ -278,6 +292,7 @@ public:
     // Filter Primitives
     void colorTransform(const LLMatrix3 &transform);
     void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue);
+    void setVignette(EVignetteMode mode, F32 gamma);
     U32* getBrightnessHistogram();
 
 protected:
@@ -292,6 +307,7 @@ protected:
 	void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ;
 
     void computeHistograms();
+    F32 getVignetteAlpha(S32 i, S32 j);
 
 public:
 	static S32 sGlobalRawMemory;
-- 
cgit v1.2.3


From 35e30759c82e0fa425e2ee5ba235868a25b44169 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Fri, 3 Jan 2014 15:44:29 -0800
Subject: ACME-1236 : WIP : Added a min value to vignette

---
 .../llimage_libtest/llimage_libtest.cpp            | 23 +++++++++++++++-------
 indra/llimage/llimage.cpp                          | 12 +++++++----
 indra/llimage/llimage.h                            |  3 ++-
 3 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 45e60f64e6..6c23a6a866 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -97,8 +97,8 @@ static const char USAGE[] = "\n"
 "        - 'darken' substracts <param> light to the image (<param> between 0 and 255).\n"
 "        - 'linearize' optimizes the contrast using the brightness histogram. <param> is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n"
 "        - 'posterize' redistributes the colors between <param> classes per channel (<param> between 2 and 255).\n"
-" -v, --vignette <name> [<feather>]\n"
-"        Apply a circular central vignette <name> to the filter using the optional <feather> value. Admissible names:\n"
+" -v, --vignette <name> [<feather> <min>]\n"
+"        Apply a circular central vignette <name> to the filter using the optional <feather> and <min> values. Admissible names:\n"
 "        - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n"
 "        - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n"
 " -log, --logmetrics <metric>\n"
@@ -371,7 +371,8 @@ int main(int argc, char** argv)
     std::string filter_name = "";
     double filter_param = 0.0;
     std::string vignette_name = "";
-    double vignette_param = 1.0;
+    double vignette_param_1 = 1.0;
+    double vignette_param_2 = 0.0;
 
 	// Init whatever is necessary
 	ll_init_apr();
@@ -591,15 +592,23 @@ int main(int argc, char** argv)
 				arg += 1;					// Skip that arg now we know it's a valid vignette name
 				if ((arg + 1) == argc)		// Break out of the loop if we reach the end of the arg list
 					break;
-                // --vignette can also have an optional parameter
+                // --vignette can also have optional parameters
                 std::string value_str;
                 value_str = argv[arg+1];    // Check the next arg
                 if (value_str[0] != '-')    // If it's not another argument, it's a vignette parameter value
                 {
-                    vignette_param = atof(value_str.c_str());
+                    vignette_param_1 = atof(value_str.c_str());
                     arg += 1;					// Skip that arg now we used it as a valid vignette param
                     if ((arg + 1) == argc)		// Break out of the loop if we reach the end of the arg list
                         break;
+                    value_str = argv[arg+1];    // Check the next arg
+                    if (value_str[0] != '-')    // If it's not another argument, it's a vignette parameter value
+                    {
+                        vignette_param_2 = atof(value_str.c_str());
+                        arg += 1;					// Skip that arg now we used it as a valid vignette param
+                        if ((arg + 1) == argc)		// Break out of the loop if we reach the end of the arg list
+                            break;
+                    }
                 }
             }
 		}
@@ -652,11 +661,11 @@ int main(int argc, char** argv)
         // Set the vignette if any
         if (vignette_name == "blend")
         {
-            raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(vignette_param));
+            raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(vignette_param_1),(float)(vignette_param_2));
         }
         else if (vignette_name == "fade")
         {
-            raw_image->setVignette(VIGNETTE_MODE_FADE,(float)(vignette_param));
+            raw_image->setVignette(VIGNETTE_MODE_FADE,(float)(vignette_param_1),(float)(vignette_param_2));
         }
         
         // Apply filter if any
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index da22ed5e5b..d84989f9c8 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -103,7 +103,8 @@ LLImageBase::LLImageBase()
       mHistoBlue(NULL),
       mHistoBrightness(NULL),
       mVignetteMode(VIGNETTE_MODE_NONE),
-      mVignetteGamma(1.0)
+      mVignetteGamma(1.0),
+      mVignetteMin(0.0)
 {
 }
 
@@ -1280,10 +1281,11 @@ void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8*
 	}
 }
 
-void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma)
+void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma, F32 min)
 {
     mVignetteMode = mode;
     mVignetteGamma = gamma;
+    mVignetteMin = llclampf(min);
     // We always center the vignette on the image and fits it in the image smallest dimension
     mVignetteCenterX = getWidth()/2;
     mVignetteCenterY = getHeight()/2;
@@ -1293,9 +1295,11 @@ void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma)
 F32 LLImageRaw::getVignetteAlpha(S32 i, S32 j)
 {
     // alpha is a modified gaussian value, with a center and fading in a circular pattern toward the edges
-    // the gamma parameter controls the intensity of the drop down from alpha 1.0 to 0.0
+    // The gamma parameter controls the intensity of the drop down from alpha 1.0 (center) to 0.0
     F32 d_center_square = (i - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY);
-    return powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f));
+    F32 alpha = powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f));
+    // We rescale alpha between min and 1.0 so to avoid complete fading if so desired.
+    return (mVignetteMin + alpha * (1.0 - mVignetteMin));
 }
 
 U32* LLImageRaw::getBrightnessHistogram()
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index b9f6a12bdd..404f1c0769 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -170,6 +170,7 @@ protected:
     S32 mVignetteCenterY;
     S32 mVignetteWidth;
     F32 mVignetteGamma;
+    F32 mVignetteMin;
     
 public:
 	static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels);
@@ -292,7 +293,7 @@ public:
     // Filter Primitives
     void colorTransform(const LLMatrix3 &transform);
     void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue);
-    void setVignette(EVignetteMode mode, F32 gamma);
+    void setVignette(EVignetteMode mode, F32 gamma, F32 min);
     U32* getBrightnessHistogram();
 
 protected:
-- 
cgit v1.2.3


From 90cbda6db0d075dccc2369a68b02919b40f53cca Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Fri, 3 Jan 2014 17:31:04 -0800
Subject: ACME-1236 : WIP : Add 2 new color correction filters. Add a la
 Instagram composite filters for testing in llimage_libtest

---
 .../llimage_libtest/llimage_libtest.cpp            | 40 +++++++++++++++++++++-
 indra/llimage/llimage.cpp                          | 33 ++++++++++++++++++
 indra/llimage/llimage.h                            |  4 ++-
 3 files changed, 75 insertions(+), 2 deletions(-)

diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 6c23a6a866..58d7f53dd1 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -716,7 +716,45 @@ int main(int argc, char** argv)
         {
             raw_image->filterEqualize((S32)(filter_param));
         }
-	
+        // Test for some "a la Instagram" filters
+        else if (filter_name == "Lomofi")
+        {
+            raw_image->setVignette(VIGNETTE_MODE_BLEND,4.0,0.0);
+            raw_image->filterLinearize(0.2);
+        }
+        else if (filter_name == "Sutro")
+        {
+            raw_image->filterLinearize(0.2);
+            raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5);
+            raw_image->filterSepia();
+        }
+        else if (filter_name == "Inkwell")
+        {
+            raw_image->filterLinearize(0.0);
+            raw_image->filterGrayScale();
+        }
+        else if (filter_name == "Poprocket")
+        {
+            LLColor4U color = LLColor4U::red;
+            color.setAlpha((U8)(0.2 * 255.0));
+            raw_image->filterLinearize(0.0);
+            raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5);
+            raw_image->filterColorize(color);
+        }
+        else if (filter_name == "Gotham")
+        {
+            raw_image->filterLinearize(0.0);
+            raw_image->filterColorBalance(1.0,1.0,20.0);
+            raw_image->filterGrayScale();
+        }
+        else if (filter_name == "Toaster")
+        {
+            raw_image->filterContrast(0.8);
+            raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5);
+            raw_image->filterBrightness(10);
+            raw_image->filterColorBalance(0.5,1.0,1.0);
+        }
+
 		// Save file
 		if (out_file != out_end)
 		{
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index d84989f9c8..3d86abb26d 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -1045,6 +1045,22 @@ void LLImageRaw::filterGamma(F32 gamma)
     colorCorrect(gamma_lut,gamma_lut,gamma_lut);
 }
 
+void LLImageRaw::filterColorBalance(F32 gamma_red, F32 gamma_green, F32 gamma_blue)
+{
+    U8 gamma_red_lut[256];
+    U8 gamma_green_lut[256];
+    U8 gamma_blue_lut[256];
+    
+    for (S32 i = 0; i < 256; i++)
+    {
+        gamma_red_lut[i]   = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_red)))));
+        gamma_green_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_green)))));
+        gamma_blue_lut[i]  = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_blue)))));
+    }
+    
+    colorCorrect(gamma_red_lut,gamma_green_lut,gamma_blue_lut);
+}
+
 void LLImageRaw::filterLinearize(F32 tail)
 {
     // Get the histogram
@@ -1191,6 +1207,23 @@ void LLImageRaw::filterBrightness(S32 add)
     colorCorrect(brightness_lut,brightness_lut,brightness_lut);
 }
 
+void LLImageRaw::filterMinMax(S32 min, S32 max)
+{
+    U8 contrast_lut[256];
+    min = llclampb(min);
+    max = llclampb(max);
+    
+    F32 slope = 255.0/(F32)(max - min);
+    F32 translate = -slope*min;
+    
+    for (S32 i = 0; i < 256; i++)
+    {
+        contrast_lut[i] = (U8)(llclampb((S32)(slope*i + translate)));
+    }
+    
+    colorCorrect(contrast_lut,contrast_lut,contrast_lut);    
+}
+
 // Filter Primitives
 void LLImageRaw::colorTransform(const LLMatrix3 &transform)
 {
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 404f1c0769..6e58453da5 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -289,7 +289,9 @@ public:
     void filterColorize(const LLColor4U& color);    // Colorize with color. Alpha will be taken into account for colorization intensity.
     void filterContrast(F32 slope);                 // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast
     void filterBrightness(S32 add);                 // Change brightness according to add: > 0 brighter, < 0 darker
-    
+    void filterColorBalance(F32 gamma_red, F32 gamma_green, F32 gamma_blue); // Change the color balance applying gammas to each channel
+    void filterMinMax(S32 min, S32 max);            // Redistribute contrast / brightness between min and max in a linear way
+   
     // Filter Primitives
     void colorTransform(const LLMatrix3 &transform);
     void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue);
-- 
cgit v1.2.3


From 3cbd0dfd849a94a789ae70f4bdc176f85cf2ba34 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Mon, 6 Jan 2014 14:46:52 -0800
Subject: ACME-1236 : WIP : Make each color correct filter use a per channel
 alpha argument, tweak Instagram-like test filters for discussion

---
 .../llimage_libtest/llimage_libtest.cpp            |  66 +++++++-----
 indra/llimage/llimage.cpp                          | 118 ++++++++++-----------
 indra/llimage/llimage.h                            |  24 +++--
 3 files changed, 111 insertions(+), 97 deletions(-)

diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 58d7f53dd1..6045ed321d 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -687,73 +687,85 @@ int main(int argc, char** argv)
         }
         else if (filter_name == "gamma")
         {
-            raw_image->filterGamma((float)(filter_param));
+            raw_image->filterGamma((float)(filter_param),LLColor3::white);
         }
         else if (filter_name == "colorize")
         {
-            // For testing, we just colorize in red, modulate by the alpha passed as a parameter
-            LLColor4U color = LLColor4U::red;
-            color.setAlpha((U8)(filter_param * 255.0));
-            raw_image->filterColorize(color);
+            // For testing, we just colorize in the red channel, modulate by the alpha passed as a parameter
+            LLColor3 color(1.0,0.0,0.0);
+            LLColor3 alpha((F32)(filter_param),0.0,0.0);
+            raw_image->filterColorize(color,alpha);
         }
         else if (filter_name == "contrast")
         {
-            raw_image->filterContrast((float)(filter_param));
+            raw_image->filterContrast((float)(filter_param),LLColor3::white);
         }
         else if (filter_name == "brighten")
         {
-            raw_image->filterBrightness((S32)(filter_param));
+            raw_image->filterBrightness((S32)(filter_param),LLColor3::white);
         }
         else if (filter_name == "darken")
         {
-            raw_image->filterBrightness((S32)(-filter_param));
+            raw_image->filterBrightness((S32)(-filter_param),LLColor3::white);
         }
         else if (filter_name == "linearize")
         {
-            raw_image->filterLinearize((float)(filter_param));
+            raw_image->filterLinearize((float)(filter_param),LLColor3::white);
         }
         else if (filter_name == "posterize")
         {
-            raw_image->filterEqualize((S32)(filter_param));
+            raw_image->filterEqualize((S32)(filter_param),LLColor3::white);
         }
         // Test for some "a la Instagram" filters
         else if (filter_name == "Lomofi")
         {
             raw_image->setVignette(VIGNETTE_MODE_BLEND,4.0,0.0);
-            raw_image->filterLinearize(0.2);
+            raw_image->filterLinearize(0.2,LLColor3::white);
+            raw_image->filterBrightness(20,LLColor3::white);
+        }
+        else if (filter_name == "Poprocket")
+        {
+            LLColor3 color(1.0,0.0,0.0);
+            LLColor3 alpha(0.5,0.0,0.0);
+            raw_image->filterLinearize(0.0,LLColor3::white);
+            raw_image->filterContrast(0.5,LLColor3::white);
+            raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5);
+            raw_image->filterColorize(color,alpha);
         }
         else if (filter_name == "Sutro")
         {
-            raw_image->filterLinearize(0.2);
+            raw_image->filterLinearize(0.2,LLColor3::white);
             raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5);
             raw_image->filterSepia();
         }
+        else if (filter_name == "Toaster")
+        {
+            raw_image->filterContrast(0.8,LLColor3::white);
+            raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5);
+            raw_image->filterBrightness(10,LLColor3::white);
+            //raw_image->filterColorBalance(0.5,1.0,1.0);
+        }
         else if (filter_name == "Inkwell")
         {
-            raw_image->filterLinearize(0.0);
+            raw_image->filterLinearize(0.0,LLColor3::white);
             raw_image->filterGrayScale();
         }
-        else if (filter_name == "Poprocket")
+        else if (filter_name == "Hefe")
         {
-            LLColor4U color = LLColor4U::red;
-            color.setAlpha((U8)(0.2 * 255.0));
-            raw_image->filterLinearize(0.0);
+            raw_image->filterLinearize(0.0,LLColor3::white);
             raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5);
-            raw_image->filterColorize(color);
+            raw_image->filterContrast(1.5,LLColor3::white);
         }
         else if (filter_name == "Gotham")
         {
-            raw_image->filterLinearize(0.0);
-            raw_image->filterColorBalance(1.0,1.0,20.0);
+            raw_image->filterLinearize(0.0,LLColor3::white);
+            // Blow out the Blue
+            LLColor3 color(0.0,0.0,0.0);
+            LLColor3 alpha(0.0,0.0,1.0);
+            raw_image->filterColorize(color,alpha);
+            // Convert to Grayscale
             raw_image->filterGrayScale();
         }
-        else if (filter_name == "Toaster")
-        {
-            raw_image->filterContrast(0.8);
-            raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5);
-            raw_image->filterBrightness(10);
-            raw_image->filterColorBalance(0.5,1.0,1.0);
-        }
 
 		// Save file
 		if (out_file != out_end)
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 3d86abb26d..977bb09b63 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -29,6 +29,7 @@
 #include "llimage.h"
 
 #include "llmath.h"
+#include "v3color.h"
 #include "v4coloru.h"
 #include "m3math.h"
 #include "v3math.h"
@@ -1033,19 +1034,7 @@ void LLImageRaw::filterRotate(F32 alpha)
     colorTransform(transfo);
 }
 
-void LLImageRaw::filterGamma(F32 gamma)
-{
-    U8 gamma_lut[256];
-    
-    for (S32 i = 0; i < 256; i++)
-    {
-        gamma_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma)))));
-    }
-    
-    colorCorrect(gamma_lut,gamma_lut,gamma_lut);
-}
-
-void LLImageRaw::filterColorBalance(F32 gamma_red, F32 gamma_green, F32 gamma_blue)
+void LLImageRaw::filterGamma(F32 gamma, const LLColor3& alpha)
 {
     U8 gamma_red_lut[256];
     U8 gamma_green_lut[256];
@@ -1053,15 +1042,17 @@ void LLImageRaw::filterColorBalance(F32 gamma_red, F32 gamma_green, F32 gamma_bl
     
     for (S32 i = 0; i < 256; i++)
     {
-        gamma_red_lut[i]   = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_red)))));
-        gamma_green_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_green)))));
-        gamma_blue_lut[i]  = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_blue)))));
+        F32 gamma_i = llclampf((float)(pow((float)(i)/255.0,gamma)));
+        // Blend in with alpha values
+        gamma_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * 255.0 * gamma_i);
+        gamma_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * 255.0 * gamma_i);
+        gamma_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * 255.0 * gamma_i);
     }
     
     colorCorrect(gamma_red_lut,gamma_green_lut,gamma_blue_lut);
 }
 
-void LLImageRaw::filterLinearize(F32 tail)
+void LLImageRaw::filterLinearize(F32 tail, const LLColor3& alpha)
 {
     // Get the histogram
     U32* histo = getBrightnessHistogram();
@@ -1093,13 +1084,19 @@ void LLImageRaw::filterLinearize(F32 tail)
     }
     
     // Compute linear lookup table
-    U8 linear_lut[256];
+    U8 linear_red_lut[256];
+    U8 linear_green_lut[256];
+    U8 linear_blue_lut[256];
     if (max_v == min_v)
     {
         // Degenerated binary split case
         for (S32 i = 0; i < 256; i++)
         {
-            linear_lut[i] = (i < min_v ? 0 : 255);
+            U8 value_i = (i < min_v ? 0 : 255);
+            // Blend in with alpha values
+            linear_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
+            linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
+            linear_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
         }
     }
     else
@@ -1109,15 +1106,19 @@ void LLImageRaw::filterLinearize(F32 tail)
         F32 translate = -min_v * slope;
         for (S32 i = 0; i < 256; i++)
         {
-            linear_lut[i] = (U8)(llclampb((S32)(slope*i + translate)));
+            U8 value_i = (U8)(llclampb((S32)(slope*i + translate)));
+            // Blend in with alpha values
+            linear_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
+            linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
+            linear_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
         }
     }
     
     // Apply lookup table
-    colorCorrect(linear_lut,linear_lut,linear_lut);    
+    colorCorrect(linear_red_lut,linear_green_lut,linear_blue_lut);
 }
 
-void LLImageRaw::filterEqualize(S32 nb_classes)
+void LLImageRaw::filterEqualize(S32 nb_classes, const LLColor3& alpha)
 {
     // Regularize the parameter: must be between 2 and 255
     nb_classes = llmax(nb_classes,2);
@@ -1142,10 +1143,15 @@ void LLImageRaw::filterEqualize(S32 nb_classes)
     S32 current_value = 0;
     
     // Compute equalized lookup table
-    U8 equalize_lut[256];
+    U8 equalize_red_lut[256];
+    U8 equalize_green_lut[256];
+    U8 equalize_blue_lut[256];
     for (S32 i = 0; i < 256; i++)
     {
-        equalize_lut[i] = (U8)(current_value);
+        // Blend in current_value with alpha values
+        equalize_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * current_value);
+        equalize_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * current_value);
+        equalize_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * current_value);
         if (cumulated_histo[i] >= current_count)
         {
             current_count += delta_count;
@@ -1155,73 +1161,65 @@ void LLImageRaw::filterEqualize(S32 nb_classes)
     }
 
     // Apply lookup table
-    colorCorrect(equalize_lut,equalize_lut,equalize_lut);
+    colorCorrect(equalize_red_lut,equalize_green_lut,equalize_blue_lut);
 }
 
-void LLImageRaw::filterColorize(const LLColor4U& color)
+void LLImageRaw::filterColorize(const LLColor3& color, const LLColor3& alpha)
 {
     U8 red_lut[256];
     U8 green_lut[256];
     U8 blue_lut[256];
     
-    F32 alpha = (F32)(color.mV[3])/255.0;
-    F32 inv_alpha = 1.0 - alpha;
-    
-    F32 red_composite   =  alpha * (F32)(color.mV[0]);
-    F32 green_composite =  alpha * (F32)(color.mV[1]);
-    F32 blue_composite  =  alpha * (F32)(color.mV[2]);
+    F32 red_composite   =  255.0 * alpha.mV[0] * color.mV[0];
+    F32 green_composite =  255.0 * alpha.mV[1] * color.mV[1];
+    F32 blue_composite  =  255.0 * alpha.mV[2] * color.mV[2];
     
     for (S32 i = 0; i < 256; i++)
     {
-        red_lut[i]   = (U8)(llclampb((S32)(inv_alpha*(F32)(i) + red_composite)));
-        green_lut[i] = (U8)(llclampb((S32)(inv_alpha*(F32)(i) + green_composite)));
-        blue_lut[i]  = (U8)(llclampb((S32)(inv_alpha*(F32)(i) + blue_composite)));
+        red_lut[i]   = (U8)(llclampb((S32)((1.0 - alpha.mV[0]) * (F32)(i) + red_composite)));
+        green_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[1]) * (F32)(i) + green_composite)));
+        blue_lut[i]  = (U8)(llclampb((S32)((1.0 - alpha.mV[2]) * (F32)(i) + blue_composite)));
     }
     
     colorCorrect(red_lut,green_lut,blue_lut);
 }
 
-void LLImageRaw::filterContrast(F32 slope)
+void LLImageRaw::filterContrast(F32 slope, const LLColor3& alpha)
 {
-    U8 contrast_lut[256];
+    U8 contrast_red_lut[256];
+    U8 contrast_green_lut[256];
+    U8 contrast_blue_lut[256];
     
     F32 translate = 128.0 * (1.0 - slope);
     
     for (S32 i = 0; i < 256; i++)
     {
-        contrast_lut[i] = (U8)(llclampb((S32)(slope*i + translate)));
+        U8 value_i = (U8)(llclampb((S32)(slope*i + translate)));
+        // Blend in with alpha values
+        contrast_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
+        contrast_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
+        contrast_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
     }
     
-    colorCorrect(contrast_lut,contrast_lut,contrast_lut);
+    colorCorrect(contrast_red_lut,contrast_green_lut,contrast_blue_lut);
 }
 
-void LLImageRaw::filterBrightness(S32 add)
+void LLImageRaw::filterBrightness(S32 add, const LLColor3& alpha)
 {
-    U8 brightness_lut[256];
-    
-    for (S32 i = 0; i < 256; i++)
-    {
-        brightness_lut[i] = (U8)(llclampb((S32)((S32)(i) + add)));
-    }
-    
-    colorCorrect(brightness_lut,brightness_lut,brightness_lut);
-}
-
-void LLImageRaw::filterMinMax(S32 min, S32 max)
-{
-    U8 contrast_lut[256];
-    min = llclampb(min);
-    max = llclampb(max);
-    
-    F32 slope = 255.0/(F32)(max - min);
-    F32 translate = -slope*min;
+    U8 brightness_red_lut[256];
+    U8 brightness_green_lut[256];
+    U8 brightness_blue_lut[256];
     
     for (S32 i = 0; i < 256; i++)
     {
-        contrast_lut[i] = (U8)(llclampb((S32)(slope*i + translate)));
+        U8 value_i = (U8)(llclampb((S32)((S32)(i) + add)));
+        // Blend in with alpha values
+        brightness_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
+        brightness_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
+        brightness_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
     }
     
-    colorCorrect(contrast_lut,contrast_lut,contrast_lut);    
+    colorCorrect(brightness_red_lut,brightness_green_lut,brightness_blue_lut);
 }
 
 // Filter Primitives
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 6e58453da5..cc91f95624 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -71,6 +71,7 @@ const S32 HTTP_PACKET_SIZE = 1496;
 class LLImageFormatted;
 class LLImageRaw;
 class LLColor4U;
+class LLColor3;
 class LLMatrix3;
 class LLPrivateMemoryPool;
 
@@ -278,19 +279,22 @@ public:
 	// Src and dst are same size.  Src has 4 components.  Dst has 3 components.
 	void compositeUnscaled4onto3( LLImageRaw* src );
     
-    // Filter Operations
+    // Filter Operations : Transforms
     void filterGrayScale();                         // Convert to grayscale
     void filterSepia();                             // Convert to sepia
     void filterSaturate(F32 saturation);            // < 1.0 desaturates, > 1.0 saturates
-    void filterRotate(F32 alpha);                   // Rotates hue according to alpha, alpha in degrees
-    void filterGamma(F32 gamma);                    // Apply gamma to all channels
-    void filterLinearize(F32 tail);                 // Use histogram to linearize constrast between min and max values minus tail
-    void filterEqualize(S32 nb_classes);            // Use histogram to equalize constrast throughout the image
-    void filterColorize(const LLColor4U& color);    // Colorize with color. Alpha will be taken into account for colorization intensity.
-    void filterContrast(F32 slope);                 // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast
-    void filterBrightness(S32 add);                 // Change brightness according to add: > 0 brighter, < 0 darker
-    void filterColorBalance(F32 gamma_red, F32 gamma_green, F32 gamma_blue); // Change the color balance applying gammas to each channel
-    void filterMinMax(S32 min, S32 max);            // Redistribute contrast / brightness between min and max in a linear way
+    void filterRotate(F32 alpha);                   // Rotates hue according to alpha, alpha is an angle in degrees
+    
+    // Filter Operations : Color Corrections
+    // When specified, the LLColor3 alpha parameter indicates the intensity of the effect for each color channel
+    // acting in effect as an alpha blending factor different for each channel. For instance (1.0,0.0,0.0) will apply
+    // the effect only to the Red channel. Intermediate values blends the effect with the source color.
+    void filterGamma(F32 gamma, const LLColor3& alpha);         // Apply gamma to each channel
+    void filterLinearize(F32 tail, const LLColor3& alpha);      // Use histogram to linearize constrast between min and max values minus tail
+    void filterEqualize(S32 nb_classes, const LLColor3& alpha); // Use histogram to equalize constrast between nb_classes throughout the image
+    void filterColorize(const LLColor3& color, const LLColor3& alpha);  // Colorize with color and alpha per channel
+    void filterContrast(F32 slope, const LLColor3& alpha);      // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast
+    void filterBrightness(S32 add, const LLColor3& alpha);      // Change brightness according to add: > 0 brighter, < 0 darker
    
     // Filter Primitives
     void colorTransform(const LLMatrix3 &transform);
-- 
cgit v1.2.3


From 5187e709c923429554ab89600a0b27cb9cedd567 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 7 Jan 2014 16:17:25 -0800
Subject: ACME-1236 : WIP : Add filter file loading and execution to
 llimage_libtest, suppress the a la Instagram tests as a result

---
 .../llimage_libtest/llimage_libtest.cpp            | 156 ++++++++++++++-------
 1 file changed, 107 insertions(+), 49 deletions(-)

diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 6045ed321d..009be0941e 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -40,6 +40,7 @@
 #include "lldir.h"
 #include "lldiriterator.h"
 #include "v4coloru.h"
+#include "llsdserialize.h"
 
 // system libraries
 #include <iostream>
@@ -97,6 +98,7 @@ static const char USAGE[] = "\n"
 "        - 'darken' substracts <param> light to the image (<param> between 0 and 255).\n"
 "        - 'linearize' optimizes the contrast using the brightness histogram. <param> is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n"
 "        - 'posterize' redistributes the colors between <param> classes per channel (<param> between 2 and 255).\n"
+"        - Any other value will be interpreted as a file name describing a sequence of filters and parameters to be applied to the input images\n"
 " -v, --vignette <name> [<feather> <min>]\n"
 "        Apply a circular central vignette <name> to the filter using the optional <feather> and <min> values. Admissible names:\n"
 "        - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n"
@@ -114,10 +116,110 @@ static const char USAGE[] = "\n"
 // true when all image loading is done. Used by metric logging thread to know when to stop the thread.
 static bool sAllDone = false;
 
+// Load filter from file
+LLSD load_filter_from_file(const std::string& file_path)
+{
+	std::cout << "Loading filter settings from : " << file_path << std::endl;
+	
+	llifstream filter_xml(file_path);
+	if (filter_xml.is_open())
+	{
+		// load and parse it
+		LLSD filter_data(LLSD::emptyArray());
+		LLPointer<LLSDParser> parser = new LLSDXMLParser();
+		parser->parse(filter_xml, filter_data, LLSDSerialize::SIZE_UNLIMITED);
+		filter_xml.close();
+		return filter_data;
+	}
+	else
+	{
+		return LLSD();
+	}
+}
+
+// Apply the filter data to the image passed as parameter
+void execute_filter(const LLSD& filter_data, LLPointer<LLImageRaw> raw_image)
+{
+	//std::cout << "Filter : size = " << filter_data.size() << std::endl;
+	for (S32 i = 0; i < filter_data.size(); ++i)
+	{
+        std::string filter_name = filter_data[i][0].asString();
+        // Dump out the filter values (for debug)
+        //std::cout << "Filter : name = " << filter_data[i][0].asString() << ", params = ";
+        //for (S32 j = 1; j < filter_data[i].size(); ++j)
+        //{
+        //    std::cout << filter_data[i][j].asString() << ", ";
+        //}
+        //std::cout << std::endl;
+        
+        // Execute the filter described on this line
+        if (filter_name == "blend")
+        {
+            raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal()));
+        }
+        else if (filter_name == "fade")
+        {
+            raw_image->setVignette(VIGNETTE_MODE_FADE,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal()));
+        }
+        else if (filter_name == "sepia")
+        {
+            raw_image->filterSepia();
+        }
+        else if (filter_name == "grayscale")
+        {
+            raw_image->filterGrayScale();
+        }
+        else if (filter_name == "saturate")
+        {
+            raw_image->filterSaturate((float)(filter_data[i][1].asReal()));
+        }
+        else if (filter_name == "rotate")
+        {
+            raw_image->filterRotate((float)(filter_data[i][1].asReal()));
+        }
+        else if (filter_name == "gamma")
+        {
+            LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal()));
+            raw_image->filterGamma((float)(filter_data[i][1].asReal()),color);
+        }
+        else if (filter_name == "colorize")
+        {
+            LLColor3 color((float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()));
+            LLColor3 alpha((F32)(filter_data[i][4].asReal()),(float)(filter_data[i][5].asReal()),(float)(filter_data[i][6].asReal()));
+            raw_image->filterColorize(color,alpha);
+        }
+        else if (filter_name == "contrast")
+        {
+            LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal()));
+            raw_image->filterContrast((float)(filter_data[i][1].asReal()),color);
+        }
+        else if (filter_name == "brighten")
+        {
+            LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal()));
+            raw_image->filterBrightness((S32)(filter_data[i][1].asReal()),color);
+        }
+        else if (filter_name == "darken")
+        {
+            LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal()));
+            raw_image->filterBrightness((S32)(-filter_data[i][1].asReal()),color);
+        }
+        else if (filter_name == "linearize")
+        {
+            LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal()));
+            raw_image->filterLinearize((float)(filter_data[i][1].asReal()),color);
+        }
+        else if (filter_name == "posterize")
+        {
+            LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal()));
+            raw_image->filterEqualize((S32)(filter_data[i][1].asReal()),color);
+        }
+    }
+}
+
 // Create an empty formatted image instance of the correct type from the filename
 LLPointer<LLImageFormatted> create_image(const std::string &filename)
 {
-	std::string exten = gDirUtilp->getExtension(filename);	
+	std::string exten = gDirUtilp->getExtension(filename);
 	LLPointer<LLImageFormatted> image = LLImageFormatted::createFromExtension(exten);
 	return image;
 }
@@ -716,55 +818,11 @@ int main(int argc, char** argv)
         {
             raw_image->filterEqualize((S32)(filter_param),LLColor3::white);
         }
-        // Test for some "a la Instagram" filters
-        else if (filter_name == "Lomofi")
+        else if (filter_name != "")
         {
-            raw_image->setVignette(VIGNETTE_MODE_BLEND,4.0,0.0);
-            raw_image->filterLinearize(0.2,LLColor3::white);
-            raw_image->filterBrightness(20,LLColor3::white);
-        }
-        else if (filter_name == "Poprocket")
-        {
-            LLColor3 color(1.0,0.0,0.0);
-            LLColor3 alpha(0.5,0.0,0.0);
-            raw_image->filterLinearize(0.0,LLColor3::white);
-            raw_image->filterContrast(0.5,LLColor3::white);
-            raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5);
-            raw_image->filterColorize(color,alpha);
-        }
-        else if (filter_name == "Sutro")
-        {
-            raw_image->filterLinearize(0.2,LLColor3::white);
-            raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5);
-            raw_image->filterSepia();
-        }
-        else if (filter_name == "Toaster")
-        {
-            raw_image->filterContrast(0.8,LLColor3::white);
-            raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5);
-            raw_image->filterBrightness(10,LLColor3::white);
-            //raw_image->filterColorBalance(0.5,1.0,1.0);
-        }
-        else if (filter_name == "Inkwell")
-        {
-            raw_image->filterLinearize(0.0,LLColor3::white);
-            raw_image->filterGrayScale();
-        }
-        else if (filter_name == "Hefe")
-        {
-            raw_image->filterLinearize(0.0,LLColor3::white);
-            raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5);
-            raw_image->filterContrast(1.5,LLColor3::white);
-        }
-        else if (filter_name == "Gotham")
-        {
-            raw_image->filterLinearize(0.0,LLColor3::white);
-            // Blow out the Blue
-            LLColor3 color(0.0,0.0,0.0);
-            LLColor3 alpha(0.0,0.0,1.0);
-            raw_image->filterColorize(color,alpha);
-            // Convert to Grayscale
-            raw_image->filterGrayScale();
+            // We're interpreting the filter as a filter file name
+            LLSD filter_data = load_filter_from_file(filter_name);
+            execute_filter(filter_data,raw_image);
         }
 
 		// Save file
-- 
cgit v1.2.3


From 0696ac9384d89fbfe234ecf664642e04891a89d4 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 7 Jan 2014 16:21:17 -0800
Subject: ACME-1236 : WIP : Add filter files to app_settings/filters (not
 loaded yet)

---
 indra/newview/app_settings/filters/Gotham.xml    | 30 ++++++++++++++++++++++++
 indra/newview/app_settings/filters/Hefe.xml      | 23 ++++++++++++++++++
 indra/newview/app_settings/filters/Inkwell.xml   | 14 +++++++++++
 indra/newview/app_settings/filters/Lomofi.xml    | 23 ++++++++++++++++++
 indra/newview/app_settings/filters/Poprocket.xml | 25 ++++++++++++++++++++
 indra/newview/app_settings/filters/Sutro.xml     | 19 +++++++++++++++
 indra/newview/app_settings/filters/Toaster.xml   | 23 ++++++++++++++++++
 7 files changed, 157 insertions(+)
 create mode 100755 indra/newview/app_settings/filters/Gotham.xml
 create mode 100755 indra/newview/app_settings/filters/Hefe.xml
 create mode 100755 indra/newview/app_settings/filters/Inkwell.xml
 create mode 100755 indra/newview/app_settings/filters/Lomofi.xml
 create mode 100755 indra/newview/app_settings/filters/Poprocket.xml
 create mode 100755 indra/newview/app_settings/filters/Sutro.xml
 create mode 100755 indra/newview/app_settings/filters/Toaster.xml

diff --git a/indra/newview/app_settings/filters/Gotham.xml b/indra/newview/app_settings/filters/Gotham.xml
new file mode 100755
index 0000000000..eb0725e6bf
--- /dev/null
+++ b/indra/newview/app_settings/filters/Gotham.xml
@@ -0,0 +1,30 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>gamma</string>
+            <real>1.5</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Hefe.xml b/indra/newview/app_settings/filters/Hefe.xml
new file mode 100755
index 0000000000..527aaee847
--- /dev/null
+++ b/indra/newview/app_settings/filters/Hefe.xml
@@ -0,0 +1,23 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>blend</string>
+            <real>4.0</real>
+            <real>0.5</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>2.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Inkwell.xml b/indra/newview/app_settings/filters/Inkwell.xml
new file mode 100755
index 0000000000..77c88b5fbb
--- /dev/null
+++ b/indra/newview/app_settings/filters/Inkwell.xml
@@ -0,0 +1,14 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.05</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Lomofi.xml b/indra/newview/app_settings/filters/Lomofi.xml
new file mode 100755
index 0000000000..f5ec911e59
--- /dev/null
+++ b/indra/newview/app_settings/filters/Lomofi.xml
@@ -0,0 +1,23 @@
+<llsd>
+    <array>
+        <array>
+            <string>blend</string>
+            <real>4.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>linearize</string>
+            <real>0.2</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>brighten</string>
+            <real>20.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Poprocket.xml b/indra/newview/app_settings/filters/Poprocket.xml
new file mode 100755
index 0000000000..7e64003908
--- /dev/null
+++ b/indra/newview/app_settings/filters/Poprocket.xml
@@ -0,0 +1,25 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>fade</string>
+            <real>4.0</real>
+            <real>0.5</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>0.4</real>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Sutro.xml b/indra/newview/app_settings/filters/Sutro.xml
new file mode 100755
index 0000000000..3b0a58f01e
--- /dev/null
+++ b/indra/newview/app_settings/filters/Sutro.xml
@@ -0,0 +1,19 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.05</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>fade</string>
+            <real>4.0</real>
+            <real>0.5</real>
+        </array>
+        <array>
+            <string>sepia</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Toaster.xml b/indra/newview/app_settings/filters/Toaster.xml
new file mode 100755
index 0000000000..170a1183ed
--- /dev/null
+++ b/indra/newview/app_settings/filters/Toaster.xml
@@ -0,0 +1,23 @@
+<llsd>
+    <array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>fade</string>
+            <real>4.0</real>
+            <real>0.5</real>
+        </array>
+        <array>
+            <string>brighten</string>
+            <real>10.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
-- 
cgit v1.2.3


From c2a974f1556906f6ca69afb5942378c8dbf85169 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 7 Jan 2014 22:10:23 -0800
Subject: ACME-1236 : WIP : Introduced screenFilter, simple creative screening
 filter

---
 .../llimage_libtest/llimage_libtest.cpp            | 11 +++++-
 indra/llimage/llimage.cpp                          | 46 ++++++++++++++++++++++
 indra/llimage/llimage.h                            |  1 +
 3 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 009be0941e..69cea33911 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -119,8 +119,7 @@ static bool sAllDone = false;
 // Load filter from file
 LLSD load_filter_from_file(const std::string& file_path)
 {
-	std::cout << "Loading filter settings from : " << file_path << std::endl;
-	
+	//std::cout << "Loading filter settings from : " << file_path << std::endl;
 	llifstream filter_xml(file_path);
 	if (filter_xml.is_open())
 	{
@@ -213,6 +212,10 @@ void execute_filter(const LLSD& filter_data, LLPointer<LLImageRaw> raw_image)
             LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal()));
             raw_image->filterEqualize((S32)(filter_data[i][1].asReal()),color);
         }
+        else if (filter_name == "screen")
+        {
+            raw_image->screenFilter((S32)(filter_data[i][1].asReal()));
+        }
     }
 }
 
@@ -818,6 +821,10 @@ int main(int argc, char** argv)
         {
             raw_image->filterEqualize((S32)(filter_param),LLColor3::white);
         }
+        else if (filter_name == "screen")
+        {
+            raw_image->screenFilter((S32)(filter_param));
+        }
         else if (filter_name != "")
         {
             // We're interpreting the filter as a filter file name
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 977bb09b63..ae3de32788 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -1312,6 +1312,52 @@ void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8*
 	}
 }
 
+void LLImageRaw::screenFilter(const S32 wave_length)
+{
+	const S32 components = getComponents();
+	llassert( components >= 1 && components <= 4 );
+    
+	S32 width  = getWidth();
+    S32 height = getHeight();
+    
+	U8* dst_data = getData();
+	for (S32 j = 0; j < height; j++)
+	{
+        for (S32 i = 0; i < width; i++)
+        {
+            F32 value = (sinf(2*F_PI*i/wave_length)*sinf(2*F_PI*j/wave_length)+1.0)*255.0/2.0;
+            //F32 value = (sinf(2*F_PI*i/wave_length)+1.0)*255.0/2.0; // will do line
+            U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0);
+            if (mVignetteMode == VIGNETTE_MODE_NONE)
+            {
+                dst_data[VRED]   = dst_value;
+                dst_data[VGREEN] = dst_value;
+                dst_data[VBLUE]  = dst_value;
+            }
+            else
+            {
+                F32 alpha = getVignetteAlpha(i,j);
+                if (mVignetteMode == VIGNETTE_MODE_BLEND)
+                {
+                    // Blends with the source image on the edges
+                    F32 inv_alpha = 1.0 - alpha;
+                    dst_data[VRED]   = inv_alpha * dst_data[VRED]   + alpha * dst_value;
+                    dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * dst_value;
+                    dst_data[VBLUE]  = inv_alpha * dst_data[VBLUE]  + alpha * dst_value;
+                }
+                else // VIGNETTE_MODE_FADE
+                {
+                    // Fade to black on the edges
+                    dst_data[VRED]   = alpha * dst_value;
+                    dst_data[VGREEN] = alpha * dst_value;
+                    dst_data[VBLUE]  = alpha * dst_value;
+                }
+            }
+            dst_data += components;
+        }
+	}
+}
+
 void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma, F32 min)
 {
     mVignetteMode = mode;
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index cc91f95624..ed17f1af21 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -299,6 +299,7 @@ public:
     // Filter Primitives
     void colorTransform(const LLMatrix3 &transform);
     void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue);
+    void screenFilter(const S32 wave_length);
     void setVignette(EVignetteMode mode, F32 gamma, F32 min);
     U32* getBrightnessHistogram();
 
-- 
cgit v1.2.3


From dea35b4bac94fa48a3fb80709370ccf26fbea424 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Wed, 8 Jan 2014 20:06:26 +0000
Subject: Removed support for secondlife:///app/slshare for ACME-1263

---
 indra/newview/llfacebookconnect.cpp | 59 +------------------------------------
 1 file changed, 1 insertion(+), 58 deletions(-)

diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index eb044d90cd..f9a3a21e94 100644
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -69,63 +69,6 @@ void toast_user_for_facebook_success()
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLSLShareHandler : public LLCommandHandler
-{
-public:
-	LLSLShareHandler() : LLCommandHandler("slshare", UNTRUSTED_THROTTLE) { }
-    
-	bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
-	{
-		if (tokens.size() >= 1)
-		{
-			if (tokens[0].asString() == "connect")
-			{
-				if (tokens.size() >= 2 && tokens[1].asString() == "flickr")
-				{
-					// this command probably came from the flickr_web browser, so close it
-					LLFloaterReg::hideInstance("flickr_web");
-
-					// connect to flickr
-					if (query_map.has("oauth_token"))
-					{
-						LLFlickrConnect::instance().connectToFlickr(query_map["oauth_token"], query_map.get("oauth_verifier"));
-					}
-					return true;
-				}
-				else if (tokens.size() >= 2 && tokens[1].asString() == "twitter")
-				{
-					// this command probably came from the twitter_web browser, so close it
-					LLFloaterReg::hideInstance("twitter_web");
-
-					// connect to twitter
-					if (query_map.has("oauth_token"))
-					{
-						LLTwitterConnect::instance().connectToTwitter(query_map["oauth_token"], query_map.get("oauth_verifier"));
-					}
-					return true;
-				}
-				else //if (tokens.size() >= 2 && tokens[1].asString() == "facebook")
-				{
-					// this command probably came from the fbc_web browser, so close it
-					LLFloaterReg::hideInstance("fbc_web");
-
-					// connect to facebook
-					if (query_map.has("code"))
-					{
-						LLFacebookConnect::instance().connectToFacebook(query_map["code"], query_map.get("state"));
-					}
-					return true;
-				}
-			}
-		}
-		return false;
-	}
-};
-LLSLShareHandler gSLShareHandler;
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// DEPRECATED - please remove once "fbc" is phased out of the web service
 class LLFacebookConnectHandler : public LLCommandHandler
 {
 public:
@@ -444,7 +387,7 @@ std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, b
     LLViewerRegion *regionp = gAgent.getRegion();
     if (regionp)
     {
-		//url = "http://pdp15.lindenlab.com/facebook/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
+		//url = "http://pdp15.lindenlab.com/fbc/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
         url = regionp->getCapability("FacebookConnect");
         url += route;
     
-- 
cgit v1.2.3


From 3161d822ab1336a347f1bb34574b5c4b8e747799 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 8 Jan 2014 15:41:42 -0800
Subject: ACME-1236 : WIP : Added mode and angle parameter to filterScreen
 (renamed for consistency)

---
 .../llimage_libtest/llimage_libtest.cpp            | 34 +++++++++++++++++++---
 indra/llimage/llimage.cpp                          | 28 +++++++++++++-----
 indra/llimage/llimage.h                            | 10 +++++--
 3 files changed, 59 insertions(+), 13 deletions(-)

diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 69cea33911..90a7c09442 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -98,7 +98,11 @@ static const char USAGE[] = "\n"
 "        - 'darken' substracts <param> light to the image (<param> between 0 and 255).\n"
 "        - 'linearize' optimizes the contrast using the brightness histogram. <param> is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n"
 "        - 'posterize' redistributes the colors between <param> classes per channel (<param> between 2 and 255).\n"
-"        - Any other value will be interpreted as a file name describing a sequence of filters and parameters to be applied to the input images\n"
+"        - 'newsscreen' applies a 2D sine screening to the red channel and output to black and white.\n"
+"        - 'horizontalscreen' applies a horizontal screening to the red channel and output to black and white.\n"
+"        - 'verticalscreen' applies a vertical screening to the red channel and output to black and white.\n"
+"        - 'slantedscreen' applies a 45 degrees slanted screening to the red channel and output to black and white.\n"
+"        - Any other value will be interpreted as a file name describing a sequence of filters and parameters to be applied to the input images.\n"
 " -v, --vignette <name> [<feather> <min>]\n"
 "        Apply a circular central vignette <name> to the filter using the optional <feather> and <min> values. Admissible names:\n"
 "        - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n"
@@ -214,7 +218,17 @@ void execute_filter(const LLSD& filter_data, LLPointer<LLImageRaw> raw_image)
         }
         else if (filter_name == "screen")
         {
-            raw_image->screenFilter((S32)(filter_data[i][1].asReal()));
+            std::string screen_name = filter_data[i][1].asString();
+            EScreenMode mode = SCREEN_MODE_2DSINE;
+            if (screen_name == "2Dsine")
+            {
+                mode = SCREEN_MODE_2DSINE;
+            }
+            else if (screen_name == "line")
+            {
+                mode = SCREEN_MODE_LINE;
+            }
+            raw_image->filterScreen(mode,(S32)(filter_data[i][2].asReal()),(F32)(filter_data[i][3].asReal()));
         }
     }
 }
@@ -821,9 +835,21 @@ int main(int argc, char** argv)
         {
             raw_image->filterEqualize((S32)(filter_param),LLColor3::white);
         }
-        else if (filter_name == "screen")
+        else if (filter_name == "newsscreen")
+        {
+            raw_image->filterScreen(SCREEN_MODE_2DSINE,(S32)(filter_param),0.0);
+        }
+        else if (filter_name == "horizontalscreen")
+        {
+            raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),0.0);
+        }
+        else if (filter_name == "verticalscreen")
+        {
+            raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),90.0);
+        }
+        else if (filter_name == "slantedscreen")
         {
-            raw_image->screenFilter((S32)(filter_param));
+            raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),45.0);
         }
         else if (filter_name != "")
         {
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index ae3de32788..a30646d846 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -1000,7 +1000,7 @@ void LLImageRaw::filterSaturate(F32 saturation)
     colorTransform(transfo);
 }
 
-void LLImageRaw::filterRotate(F32 alpha)
+void LLImageRaw::filterRotate(F32 angle)
 {
     // Matrix to Lij
     LLMatrix3 r_a;
@@ -1024,9 +1024,9 @@ void LLImageRaw::filterRotate(F32 alpha)
     
     // Local color rotation transform
     LLMatrix3 r;
-    alpha *= DEG_TO_RAD;
-    r.setRows(LLVector3( cosf(alpha), sinf(alpha), 0.0),
-              LLVector3(-sinf(alpha), cosf(alpha), 0.0),
+    angle *= DEG_TO_RAD;
+    r.setRows(LLVector3( cosf(angle), sinf(angle), 0.0),
+              LLVector3(-sinf(angle), cosf(angle), 0.0),
               LLVector3( 0.0,         0.0,         1.0));
     
     // Global color rotation transform
@@ -1312,7 +1312,7 @@ void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8*
 	}
 }
 
-void LLImageRaw::screenFilter(const S32 wave_length)
+void LLImageRaw::filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle)
 {
 	const S32 components = getComponents();
 	llassert( components >= 1 && components <= 4 );
@@ -1320,14 +1320,28 @@ void LLImageRaw::screenFilter(const S32 wave_length)
 	S32 width  = getWidth();
     S32 height = getHeight();
     
+    F32 sin = sinf(angle*DEG_TO_RAD);
+    F32 cos = cosf(angle*DEG_TO_RAD);
+    
 	U8* dst_data = getData();
 	for (S32 j = 0; j < height; j++)
 	{
         for (S32 i = 0; i < width; i++)
         {
-            F32 value = (sinf(2*F_PI*i/wave_length)*sinf(2*F_PI*j/wave_length)+1.0)*255.0/2.0;
-            //F32 value = (sinf(2*F_PI*i/wave_length)+1.0)*255.0/2.0; // will do line
+            F32 value = 0.0;
+            F32 d = 0.0;
+            switch (mode)
+            {
+                case SCREEN_MODE_2DSINE:
+                    value = (sinf(2*F_PI*i/wave_length)*sinf(2*F_PI*j/wave_length)+1.0)*255.0/2.0;
+                    break;
+                case SCREEN_MODE_LINE:
+                    d = sin*i - cos*j;
+                    value = (sinf(2*F_PI*d/wave_length)+1.0)*255.0/2.0;
+                    break;
+            }
             U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0);
+            
             if (mVignetteMode == VIGNETTE_MODE_NONE)
             {
                 dst_data[VRED]   = dst_value;
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index ed17f1af21..f2bb91a329 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -95,6 +95,12 @@ typedef enum e_vignette_mode
 	VIGNETTE_MODE_FADE  = 2
 } EVignetteMode;
 
+typedef enum e_screen_mode
+{
+	SCREEN_MODE_2DSINE   = 0,
+	SCREEN_MODE_LINE     = 1
+} EScreenMode;
+
 //============================================================================
 // library initialization class
 
@@ -283,7 +289,7 @@ public:
     void filterGrayScale();                         // Convert to grayscale
     void filterSepia();                             // Convert to sepia
     void filterSaturate(F32 saturation);            // < 1.0 desaturates, > 1.0 saturates
-    void filterRotate(F32 alpha);                   // Rotates hue according to alpha, alpha is an angle in degrees
+    void filterRotate(F32 angle);                   // Rotates hue according to angle, angle in degrees
     
     // Filter Operations : Color Corrections
     // When specified, the LLColor3 alpha parameter indicates the intensity of the effect for each color channel
@@ -299,7 +305,7 @@ public:
     // Filter Primitives
     void colorTransform(const LLMatrix3 &transform);
     void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue);
-    void screenFilter(const S32 wave_length);
+    void filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle);
     void setVignette(EVignetteMode mode, F32 gamma, F32 min);
     U32* getBrightnessHistogram();
 
-- 
cgit v1.2.3


From 1c705489c47e038200c5e0493b4a310bef10a0e1 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 8 Jan 2014 15:42:52 -0800
Subject: ACME-1236 : WIP : Added Newspaper filter to the bank of filters

---
 indra/newview/app_settings/filters/Newspaper.xml | 25 ++++++++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100755 indra/newview/app_settings/filters/Newspaper.xml

diff --git a/indra/newview/app_settings/filters/Newspaper.xml b/indra/newview/app_settings/filters/Newspaper.xml
new file mode 100755
index 0000000000..7480325542
--- /dev/null
+++ b/indra/newview/app_settings/filters/Newspaper.xml
@@ -0,0 +1,25 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.2</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+        <array>
+            <string>blend</string>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>screen</string>
+            <string>2Dsine</string>
+            <real>15.0</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
-- 
cgit v1.2.3


From 70b877da0eccca2e11c810a92c0a928baf802334 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 8 Jan 2014 21:19:21 -0800
Subject: Fix ambiguous pow call (use powf) instead

---
 indra/llimage/llimage.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index a30646d846..14fa71d828 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -1042,7 +1042,7 @@ void LLImageRaw::filterGamma(F32 gamma, const LLColor3& alpha)
     
     for (S32 i = 0; i < 256; i++)
     {
-        F32 gamma_i = llclampf((float)(pow((float)(i)/255.0,gamma)));
+        F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,gamma)));
         // Blend in with alpha values
         gamma_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * 255.0 * gamma_i);
         gamma_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * 255.0 * gamma_i);
-- 
cgit v1.2.3


From 7d8e4020750683412c9f56edf847fd830402aa0f Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Thu, 9 Jan 2014 17:25:01 -0800
Subject: ACME-1244 : WIP : Move files around and introduced an
 llimagefiltersmanager to get the filters

---
 indra/newview/CMakeLists.txt                       |  2 +
 indra/newview/app_settings/filters/Gotham.xml      | 30 --------
 indra/newview/app_settings/filters/Grayscale.xml   | 21 ++++++
 indra/newview/app_settings/filters/GreenGray.xml   | 24 +++++++
 indra/newview/app_settings/filters/HLines.xml      | 25 +++++++
 indra/newview/app_settings/filters/Hefe.xml        | 23 ------
 indra/newview/app_settings/filters/Inkwell.xml     | 14 ----
 indra/newview/app_settings/filters/Lomofi.xml      | 23 ------
 indra/newview/app_settings/filters/Newspaper.xml   |  4 +-
 indra/newview/app_settings/filters/Poprocket.xml   | 25 -------
 indra/newview/app_settings/filters/RedV.xml        | 32 +++++++++
 indra/newview/app_settings/filters/Saturate30.xml  |  8 +++
 indra/newview/app_settings/filters/SepiaV.xml      | 26 +++++++
 indra/newview/app_settings/filters/Sutro.xml       | 19 -----
 indra/newview/app_settings/filters/Toaster.xml     | 23 ------
 indra/newview/app_settings/filters/VividV.xml      | 45 ++++++++++++
 .../newview/app_settings/filters/VividYellowV.xml  | 39 ++++++++++
 indra/newview/app_settings/filters/YellowV.xml     | 41 +++++++++++
 indra/newview/llimagefiltersmanager.cpp            | 84 ++++++++++++++++++++++
 indra/newview/llimagefiltersmanager.h              | 74 +++++++++++++++++++
 indra/newview/viewer_manifest.py                   |  3 +
 21 files changed, 426 insertions(+), 159 deletions(-)
 delete mode 100755 indra/newview/app_settings/filters/Gotham.xml
 create mode 100755 indra/newview/app_settings/filters/Grayscale.xml
 create mode 100755 indra/newview/app_settings/filters/GreenGray.xml
 create mode 100755 indra/newview/app_settings/filters/HLines.xml
 delete mode 100755 indra/newview/app_settings/filters/Hefe.xml
 delete mode 100755 indra/newview/app_settings/filters/Inkwell.xml
 delete mode 100755 indra/newview/app_settings/filters/Lomofi.xml
 delete mode 100755 indra/newview/app_settings/filters/Poprocket.xml
 create mode 100755 indra/newview/app_settings/filters/RedV.xml
 create mode 100755 indra/newview/app_settings/filters/Saturate30.xml
 create mode 100755 indra/newview/app_settings/filters/SepiaV.xml
 delete mode 100755 indra/newview/app_settings/filters/Sutro.xml
 delete mode 100755 indra/newview/app_settings/filters/Toaster.xml
 create mode 100755 indra/newview/app_settings/filters/VividV.xml
 create mode 100755 indra/newview/app_settings/filters/VividYellowV.xml
 create mode 100755 indra/newview/app_settings/filters/YellowV.xml
 create mode 100755 indra/newview/llimagefiltersmanager.cpp
 create mode 100755 indra/newview/llimagefiltersmanager.h

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 828849a327..e458193142 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -328,6 +328,7 @@ set(viewer_SOURCE_FILES
     llfloaterimsessiontab.cpp
     llfloaterimsession.cpp
     llfloaterimcontainer.cpp
+    llimagefiltersmanager.cpp
     llimhandler.cpp
     llimview.cpp
     llinspect.cpp
@@ -919,6 +920,7 @@ set(viewer_HEADER_FILES
     llfloaterimsessiontab.h
     llfloaterimsession.h
     llfloaterimcontainer.h
+    llimagefiltersmanager.h
     llimview.h
     llinspect.h
     llinspectavatar.h
diff --git a/indra/newview/app_settings/filters/Gotham.xml b/indra/newview/app_settings/filters/Gotham.xml
deleted file mode 100755
index eb0725e6bf..0000000000
--- a/indra/newview/app_settings/filters/Gotham.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>gamma</string>
-            <real>1.5</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>colorize</string>
-            <real>0.0</real>
-            <real>0.0</real>
-            <real>0.0</real>
-            <real>0.0</real>
-            <real>0.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>grayscale</string>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/Grayscale.xml b/indra/newview/app_settings/filters/Grayscale.xml
new file mode 100755
index 0000000000..101ed8233a
--- /dev/null
+++ b/indra/newview/app_settings/filters/Grayscale.xml
@@ -0,0 +1,21 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.01</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/GreenGray.xml b/indra/newview/app_settings/filters/GreenGray.xml
new file mode 100755
index 0000000000..dce5ab3e9e
--- /dev/null
+++ b/indra/newview/app_settings/filters/GreenGray.xml
@@ -0,0 +1,24 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.3</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>saturate</string>
+            <real>0.35</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/HLines.xml b/indra/newview/app_settings/filters/HLines.xml
new file mode 100755
index 0000000000..ddff4d1977
--- /dev/null
+++ b/indra/newview/app_settings/filters/HLines.xml
@@ -0,0 +1,25 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+        <array>
+            <string>blend</string>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>screen</string>
+            <string>line</string>
+            <real>5.0</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Hefe.xml b/indra/newview/app_settings/filters/Hefe.xml
deleted file mode 100755
index 527aaee847..0000000000
--- a/indra/newview/app_settings/filters/Hefe.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>blend</string>
-            <real>4.0</real>
-            <real>0.5</real>
-        </array>
-        <array>
-            <string>contrast</string>
-            <real>2.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/Inkwell.xml b/indra/newview/app_settings/filters/Inkwell.xml
deleted file mode 100755
index 77c88b5fbb..0000000000
--- a/indra/newview/app_settings/filters/Inkwell.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.05</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>grayscale</string>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/Lomofi.xml b/indra/newview/app_settings/filters/Lomofi.xml
deleted file mode 100755
index f5ec911e59..0000000000
--- a/indra/newview/app_settings/filters/Lomofi.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>blend</string>
-            <real>4.0</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>linearize</string>
-            <real>0.2</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>brighten</string>
-            <real>20.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/Newspaper.xml b/indra/newview/app_settings/filters/Newspaper.xml
index 7480325542..8247c34500 100755
--- a/indra/newview/app_settings/filters/Newspaper.xml
+++ b/indra/newview/app_settings/filters/Newspaper.xml
@@ -2,7 +2,7 @@
     <array>
         <array>
             <string>linearize</string>
-            <real>0.2</real>
+            <real>0.1</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
@@ -18,7 +18,7 @@
         <array>
             <string>screen</string>
             <string>2Dsine</string>
-            <real>15.0</real>
+            <real>5.0</real>
             <real>0.0</real>
         </array>
     </array>
diff --git a/indra/newview/app_settings/filters/Poprocket.xml b/indra/newview/app_settings/filters/Poprocket.xml
deleted file mode 100755
index 7e64003908..0000000000
--- a/indra/newview/app_settings/filters/Poprocket.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>fade</string>
-            <real>4.0</real>
-            <real>0.5</real>
-        </array>
-        <array>
-            <string>colorize</string>
-            <real>1.0</real>
-            <real>0.0</real>
-            <real>0.0</real>
-            <real>0.4</real>
-            <real>0.0</real>
-            <real>0.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/RedV.xml b/indra/newview/app_settings/filters/RedV.xml
new file mode 100755
index 0000000000..5c47ca0f84
--- /dev/null
+++ b/indra/newview/app_settings/filters/RedV.xml
@@ -0,0 +1,32 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>fade</string>
+            <real>4.0</real>
+            <real>0.5</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>0.4</real>
+            <real>0.0</real>
+            <real>0.2</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Saturate30.xml b/indra/newview/app_settings/filters/Saturate30.xml
new file mode 100755
index 0000000000..b77f07a037
--- /dev/null
+++ b/indra/newview/app_settings/filters/Saturate30.xml
@@ -0,0 +1,8 @@
+<llsd>
+    <array>
+        <array>
+            <string>saturate</string>
+            <real>3.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/SepiaV.xml b/indra/newview/app_settings/filters/SepiaV.xml
new file mode 100755
index 0000000000..d26df608b9
--- /dev/null
+++ b/indra/newview/app_settings/filters/SepiaV.xml
@@ -0,0 +1,26 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.01</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>fade</string>
+            <real>4.0</real>
+            <real>0.5</real>
+        </array>
+        <array>
+            <string>sepia</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Sutro.xml b/indra/newview/app_settings/filters/Sutro.xml
deleted file mode 100755
index 3b0a58f01e..0000000000
--- a/indra/newview/app_settings/filters/Sutro.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.05</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>fade</string>
-            <real>4.0</real>
-            <real>0.5</real>
-        </array>
-        <array>
-            <string>sepia</string>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/Toaster.xml b/indra/newview/app_settings/filters/Toaster.xml
deleted file mode 100755
index 170a1183ed..0000000000
--- a/indra/newview/app_settings/filters/Toaster.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>contrast</string>
-            <real>0.8</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>fade</string>
-            <real>4.0</real>
-            <real>0.5</real>
-        </array>
-        <array>
-            <string>brighten</string>
-            <real>10.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/VividV.xml b/indra/newview/app_settings/filters/VividV.xml
new file mode 100755
index 0000000000..203130bdee
--- /dev/null
+++ b/indra/newview/app_settings/filters/VividV.xml
@@ -0,0 +1,45 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>saturate</string>
+            <real>1.5</real>
+        </array>
+        <array>
+            <string>fade</string>
+            <real>1.0</real>
+            <real>0.25</real>
+        </array>
+        <array>
+            <string>saturate</string>
+            <real>0.8</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>1.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>brighten</string>
+            <real>30</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/VividYellowV.xml b/indra/newview/app_settings/filters/VividYellowV.xml
new file mode 100755
index 0000000000..2da27e53c1
--- /dev/null
+++ b/indra/newview/app_settings/filters/VividYellowV.xml
@@ -0,0 +1,39 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>1.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>fade</string>
+            <real>1.0</real>
+            <real>0.25</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.3</real>
+            <real>0.2</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>1.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/YellowV.xml b/indra/newview/app_settings/filters/YellowV.xml
new file mode 100755
index 0000000000..0dab2489a0
--- /dev/null
+++ b/indra/newview/app_settings/filters/YellowV.xml
@@ -0,0 +1,41 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.5</real>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>blend</string>
+            <real>10.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.1</real>
+            <real>0.1</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/llimagefiltersmanager.cpp b/indra/newview/llimagefiltersmanager.cpp
new file mode 100755
index 0000000000..efc4f56ad3
--- /dev/null
+++ b/indra/newview/llimagefiltersmanager.cpp
@@ -0,0 +1,84 @@
+/** 
+ * @file llimagefilters.cpp
+ * @brief Load and execute image filters. Mostly used for Flickr at the moment.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2014, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llimagefilters.h"
+
+#include "lldiriterator.h"
+
+
+//---------------------------------------------------------------------------
+// LLImageFilters
+//---------------------------------------------------------------------------
+
+LLImageFilters::LLImageFilters()
+{
+}
+
+LLImageFilters::~LLImageFilters()
+{
+}
+
+// virtual static
+void LLImageFilters::initSingleton()
+{
+	loadAllFilters();
+}
+
+// static
+std::string LLImageFilters::getSysDir()
+{
+	return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "filters", "");
+}
+
+void LLImageFilters::loadAllFilters()
+{
+	// Load system (coming out of the box) filters
+	loadFiltersFromDir(getSysDir());
+}
+
+void LLImageFilters::loadFiltersFromDir(const std::string& dir)
+{
+	LLDirIterator dir_iter(dir, "*.xml");
+	while (1)
+	{
+		std::string file;
+		if (!dir_iter.next(file))
+		{
+			break; // no more files
+		}
+        
+		std::string path = gDirUtilp->add(dir, file);
+
+        // For the moment, just output the file found to the log
+        llinfos << "Merov : loadFiltersFromDir, filter = " << path << llendl;
+	}
+}
+
+
+
+//============================================================================
diff --git a/indra/newview/llimagefiltersmanager.h b/indra/newview/llimagefiltersmanager.h
new file mode 100755
index 0000000000..52b4a56b9b
--- /dev/null
+++ b/indra/newview/llimagefiltersmanager.h
@@ -0,0 +1,74 @@
+/** 
+ * @file llimagefilters.h
+ * @brief Load and execute image filters. Mostly used for Flickr at the moment.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2014, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLIMAGEFILTERS_H
+#define LL_LLIMAGEFILTERS_H
+
+#include "llsingleton.h"
+#include "llimage.h"
+/*
+typedef enum e_vignette_mode
+{
+	VIGNETTE_MODE_NONE  = 0,
+	VIGNETTE_MODE_BLEND = 1,
+	VIGNETTE_MODE_FADE  = 2
+} EVignetteMode;
+
+typedef enum e_screen_mode
+{
+	SCREEN_MODE_2DSINE   = 0,
+	SCREEN_MODE_LINE     = 1
+} EScreenMode;
+*/
+//============================================================================
+// library initialization class
+
+class LLImageFilters : public LLSingleton<LLImageFilters>
+{
+	LOG_CLASS(LLImageFilters);
+public:
+    // getFilters(); get a vector of std::string containing the filter names
+    //LLSD loadFilter(const std::string& filter_name);
+    //void executeFilter(const LLSD& filter_data, LLPointer<LLImageRaw> raw_image);
+   
+protected:
+private:
+	void loadAllFilters();
+	void loadFiltersFromDir(const std::string& dir);
+	LLSD loadFilter(const std::string& path);
+    
+	static std::string getSysDir();
+    
+    friend class LLSingleton<LLImageFilters>;
+	/*virtual*/ void initSingleton();
+	LLImageFilters();
+	~LLImageFilters();
+    
+    // Needed here:
+    // - a map of filter files with name and path
+};
+
+#endif
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 9e8623c1f9..3a76773dde 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -98,6 +98,9 @@ class ViewerManifest(LLManifest):
                 # ... and the entire windlight directory
                 self.path("windlight")
 
+                # ... and the entire image filters directory
+                self.path("filters")
+            
                 # ... and the included spell checking dictionaries
                 pkgdir = os.path.join(self.args['build'], os.pardir, 'packages')
                 if self.prefix(src=pkgdir,dst=""):
-- 
cgit v1.2.3


From 0c7cab771cb7972ed44eedf0c16133ef082eb9e1 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Thu, 9 Jan 2014 21:58:30 -0800
Subject: ACME-1236 : Add lines as a new type of vignette and Brightscan as an
 example

---
 .../llimage_libtest/llimage_libtest.cpp            | 12 +++++++----
 indra/llimage/llimage.cpp                          | 21 +++++++++++++++-----
 indra/llimage/llimage.h                            |  9 ++++++++-
 indra/newview/app_settings/filters/Brightscan.xml  | 23 ++++++++++++++++++++++
 4 files changed, 55 insertions(+), 10 deletions(-)
 create mode 100755 indra/newview/app_settings/filters/Brightscan.xml

diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 90a7c09442..2447e00028 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -158,11 +158,15 @@ void execute_filter(const LLSD& filter_data, LLPointer<LLImageRaw> raw_image)
         // Execute the filter described on this line
         if (filter_name == "blend")
         {
-            raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal()));
+            raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal()));
         }
         else if (filter_name == "fade")
         {
-            raw_image->setVignette(VIGNETTE_MODE_FADE,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal()));
+            raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal()));
+        }
+        else if (filter_name == "lines")
+        {
+            raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal()));
         }
         else if (filter_name == "sepia")
         {
@@ -780,11 +784,11 @@ int main(int argc, char** argv)
         // Set the vignette if any
         if (vignette_name == "blend")
         {
-            raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(vignette_param_1),(float)(vignette_param_2));
+            raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2));
         }
         else if (vignette_name == "fade")
         {
-            raw_image->setVignette(VIGNETTE_MODE_FADE,(float)(vignette_param_1),(float)(vignette_param_2));
+            raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2));
         }
         
         // Apply filter if any
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 14fa71d828..3105fe3746 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -1372,9 +1372,10 @@ void LLImageRaw::filterScreen(EScreenMode mode, const S32 wave_length, const F32
 	}
 }
 
-void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma, F32 min)
+void LLImageRaw::setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min)
 {
     mVignetteMode = mode;
+    mVignetteType = type;
     mVignetteGamma = gamma;
     mVignetteMin = llclampf(min);
     // We always center the vignette on the image and fits it in the image smallest dimension
@@ -1385,10 +1386,20 @@ void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma, F32 min)
 
 F32 LLImageRaw::getVignetteAlpha(S32 i, S32 j)
 {
-    // alpha is a modified gaussian value, with a center and fading in a circular pattern toward the edges
-    // The gamma parameter controls the intensity of the drop down from alpha 1.0 (center) to 0.0
-    F32 d_center_square = (i - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY);
-    F32 alpha = powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f));
+    F32 alpha = 1.0;
+    if (mVignetteType == VIGNETTE_TYPE_CENTER)
+    {
+        // alpha is a modified gaussian value, with a center and fading in a circular pattern toward the edges
+        // The gamma parameter controls the intensity of the drop down from alpha 1.0 (center) to 0.0
+        F32 d_center_square = (i - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY);
+        alpha = powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f));
+    }
+    else if (mVignetteType == VIGNETTE_TYPE_LINES)
+    {
+        // alpha varies according to a squared sine function vertically.
+        // gamma is interpreted as the wavelength (in pixels) of the sine in that case.
+        alpha = (sinf(2*F_PI*j/mVignetteGamma) > 0.0 ? 1.0 : 0.0);
+    }
     // We rescale alpha between min and 1.0 so to avoid complete fading if so desired.
     return (mVignetteMin + alpha * (1.0 - mVignetteMin));
 }
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index f2bb91a329..a600f2e4a6 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -95,6 +95,12 @@ typedef enum e_vignette_mode
 	VIGNETTE_MODE_FADE  = 2
 } EVignetteMode;
 
+typedef enum e_vignette_type
+{
+	VIGNETTE_TYPE_CENTER = 0,
+	VIGNETTE_TYPE_LINES  = 1
+} EVignetteType;
+
 typedef enum e_screen_mode
 {
 	SCREEN_MODE_2DSINE   = 0,
@@ -173,6 +179,7 @@ protected:
     
     // Vignette filtering
     EVignetteMode mVignetteMode;
+    EVignetteType mVignetteType;
     S32 mVignetteCenterX;
     S32 mVignetteCenterY;
     S32 mVignetteWidth;
@@ -306,7 +313,7 @@ public:
     void colorTransform(const LLMatrix3 &transform);
     void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue);
     void filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle);
-    void setVignette(EVignetteMode mode, F32 gamma, F32 min);
+    void setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min);
     U32* getBrightnessHistogram();
 
 protected:
diff --git a/indra/newview/app_settings/filters/Brightscan.xml b/indra/newview/app_settings/filters/Brightscan.xml
new file mode 100755
index 0000000000..8b10687ef5
--- /dev/null
+++ b/indra/newview/app_settings/filters/Brightscan.xml
@@ -0,0 +1,23 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.01</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>lines</string>
+            <real>10.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>brighten</string>
+            <real>100.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
-- 
cgit v1.2.3


From 2202150af43a44ecf3d989f21ebf4ce5f79a23cc Mon Sep 17 00:00:00 2001
From: merov <none@none>
Date: Sat, 11 Jan 2014 01:00:35 +0000
Subject: ACME-1243 : WIP : Populate filter drop down with filter list
 dynamically

---
 indra/newview/llfloaterflickr.cpp       |  9 +++++++++
 indra/newview/llimagefiltersmanager.cpp | 24 +++++++++++++++---------
 indra/newview/llimagefiltersmanager.h   | 27 ++++++++++++++-------------
 3 files changed, 38 insertions(+), 22 deletions(-)

diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 675266143d..8395c0db5a 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -36,6 +36,7 @@
 #include "llflickrconnect.h"
 #include "llfloaterreg.h"
 #include "lliconctrl.h"
+#include "llimagefiltersmanager.h"
 #include "llresmgr.h"		// LLLocale
 #include "llsdserialize.h"
 #include "llloadingindicator.h"
@@ -106,6 +107,14 @@ BOOL LLFlickrPhotoPanel::postBuild()
 	mPostButton = getChild<LLUICtrl>("post_photo_btn");
 	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
 
+	// Update filter list
+    std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
+	LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
+    for (U32 i = 0; i < filter_list.size(); i++) 
+	{
+        filterbox->add(filter_list[i]);
+    }
+
 	return LLPanel::postBuild();
 }
 
diff --git a/indra/newview/llimagefiltersmanager.cpp b/indra/newview/llimagefiltersmanager.cpp
index efc4f56ad3..888e5ec5dd 100644
--- a/indra/newview/llimagefiltersmanager.cpp
+++ b/indra/newview/llimagefiltersmanager.cpp
@@ -1,5 +1,5 @@
 /** 
- * @file llimagefilters.cpp
+ * @file llimagefiltersmanager.cpp
  * @brief Load and execute image filters. Mostly used for Flickr at the moment.
  *
  * $LicenseInfo:firstyear=2001&license=viewerlgpl$
@@ -26,7 +26,7 @@
 
 #include "llviewerprecompiledheaders.h"
 
-#include "llimagefilters.h"
+#include "llimagefiltersmanager.h"
 
 #include "lldiriterator.h"
 
@@ -35,34 +35,36 @@
 // LLImageFilters
 //---------------------------------------------------------------------------
 
-LLImageFilters::LLImageFilters()
+LLImageFiltersManager::LLImageFiltersManager()
 {
 }
 
-LLImageFilters::~LLImageFilters()
+LLImageFiltersManager::~LLImageFiltersManager()
 {
 }
 
 // virtual static
-void LLImageFilters::initSingleton()
+void LLImageFiltersManager::initSingleton()
 {
 	loadAllFilters();
 }
 
 // static
-std::string LLImageFilters::getSysDir()
+std::string LLImageFiltersManager::getSysDir()
 {
 	return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "filters", "");
 }
 
-void LLImageFilters::loadAllFilters()
+void LLImageFiltersManager::loadAllFilters()
 {
 	// Load system (coming out of the box) filters
 	loadFiltersFromDir(getSysDir());
 }
 
-void LLImageFilters::loadFiltersFromDir(const std::string& dir)
+void LLImageFiltersManager::loadFiltersFromDir(const std::string& dir)
 {
+	mFiltersList.clear();
+
 	LLDirIterator dir_iter(dir, "*.xml");
 	while (1)
 	{
@@ -71,11 +73,15 @@ void LLImageFilters::loadFiltersFromDir(const std::string& dir)
 		{
 			break; // no more files
 		}
+		
+		// Get the ".xml" out of the file name to get the filter name
+		std::string filter_name = file.substr(0,file.length()-4);
+        mFiltersList.push_back(filter_name);
         
 		std::string path = gDirUtilp->add(dir, file);
 
         // For the moment, just output the file found to the log
-        llinfos << "Merov : loadFiltersFromDir, filter = " << path << llendl;
+        llinfos << "Merov : loadFiltersFromDir, filter = " << file << ",path = " << path << llendl;
 	}
 }
 
diff --git a/indra/newview/llimagefiltersmanager.h b/indra/newview/llimagefiltersmanager.h
index 52b4a56b9b..e916dc7187 100644
--- a/indra/newview/llimagefiltersmanager.h
+++ b/indra/newview/llimagefiltersmanager.h
@@ -1,5 +1,5 @@
 /** 
- * @file llimagefilters.h
+ * @file llimagefiltersmanager.h
  * @brief Load and execute image filters. Mostly used for Flickr at the moment.
  *
  * $LicenseInfo:firstyear=2000&license=viewerlgpl$
@@ -24,8 +24,8 @@
  * $/LicenseInfo$
  */
 
-#ifndef LL_LLIMAGEFILTERS_H
-#define LL_LLIMAGEFILTERS_H
+#ifndef LL_LLIMAGEFILTERSMANAGER_H
+#define LL_LLIMAGEFILTERSMANAGER_H
 
 #include "llsingleton.h"
 #include "llimage.h"
@@ -46,29 +46,30 @@ typedef enum e_screen_mode
 //============================================================================
 // library initialization class
 
-class LLImageFilters : public LLSingleton<LLImageFilters>
+class LLImageFiltersManager : public LLSingleton<LLImageFiltersManager>
 {
-	LOG_CLASS(LLImageFilters);
+	LOG_CLASS(LLImageFiltersManager);
 public:
     // getFilters(); get a vector of std::string containing the filter names
     //LLSD loadFilter(const std::string& filter_name);
     //void executeFilter(const LLSD& filter_data, LLPointer<LLImageRaw> raw_image);
-   
+    const std::vector<std::string> &getFiltersList() const { return mFiltersList; }
+  
 protected:
 private:
 	void loadAllFilters();
 	void loadFiltersFromDir(const std::string& dir);
-	LLSD loadFilter(const std::string& path);
+//	LLSD loadFilter(const std::string& path);
     
 	static std::string getSysDir();
     
-    friend class LLSingleton<LLImageFilters>;
+    friend class LLSingleton<LLImageFiltersManager>;
 	/*virtual*/ void initSingleton();
-	LLImageFilters();
-	~LLImageFilters();
+	LLImageFiltersManager();
+	~LLImageFiltersManager();
     
-    // Needed here:
-    // - a map of filter files with name and path
+	// List of filters
+    std::vector<std::string> mFiltersList;
 };
 
-#endif
+#endif // LL_LLIMAGEFILTERSMANAGER_H
-- 
cgit v1.2.3


From 5342d0c570ef6c654b63a403d9aa7b51ef65f249 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Mon, 13 Jan 2014 14:36:42 -0800
Subject: ACME-1256 : Rename and cleanup in the default filters

---
 indra/newview/app_settings/filters/1970s color.xml | 41 ++++++++++++++++++++
 .../newview/app_settings/filters/Black & white.xml | 21 ++++++++++
 indra/newview/app_settings/filters/Brightscan.xml  | 23 -----------
 indra/newview/app_settings/filters/Grayscale.xml   | 21 ----------
 indra/newview/app_settings/filters/GreenGray.xml   | 24 ------------
 indra/newview/app_settings/filters/HLines.xml      | 25 ------------
 indra/newview/app_settings/filters/Heatwave.xml    | 32 +++++++++++++++
 indra/newview/app_settings/filters/Intense.xml     |  8 ++++
 indra/newview/app_settings/filters/Jules Verne.xml | 25 ++++++++++++
 indra/newview/app_settings/filters/Overcast.xml    | 24 ++++++++++++
 indra/newview/app_settings/filters/RedV.xml        | 32 ---------------
 indra/newview/app_settings/filters/Saturate30.xml  |  8 ----
 indra/newview/app_settings/filters/Sepia.xml       | 26 +++++++++++++
 indra/newview/app_settings/filters/SepiaV.xml      | 26 -------------
 indra/newview/app_settings/filters/Spotlight.xml   | 45 ++++++++++++++++++++++
 indra/newview/app_settings/filters/Video.xml       | 23 +++++++++++
 indra/newview/app_settings/filters/VividV.xml      | 45 ----------------------
 .../newview/app_settings/filters/VividYellowV.xml  | 39 -------------------
 indra/newview/app_settings/filters/YellowV.xml     | 41 --------------------
 .../skins/default/xui/en/panel_flickr_photo.xml    |  4 --
 20 files changed, 245 insertions(+), 288 deletions(-)
 create mode 100644 indra/newview/app_settings/filters/1970s color.xml
 create mode 100644 indra/newview/app_settings/filters/Black & white.xml
 delete mode 100755 indra/newview/app_settings/filters/Brightscan.xml
 delete mode 100644 indra/newview/app_settings/filters/Grayscale.xml
 delete mode 100644 indra/newview/app_settings/filters/GreenGray.xml
 delete mode 100644 indra/newview/app_settings/filters/HLines.xml
 create mode 100644 indra/newview/app_settings/filters/Heatwave.xml
 create mode 100644 indra/newview/app_settings/filters/Intense.xml
 create mode 100644 indra/newview/app_settings/filters/Jules Verne.xml
 create mode 100644 indra/newview/app_settings/filters/Overcast.xml
 delete mode 100644 indra/newview/app_settings/filters/RedV.xml
 delete mode 100644 indra/newview/app_settings/filters/Saturate30.xml
 create mode 100644 indra/newview/app_settings/filters/Sepia.xml
 delete mode 100644 indra/newview/app_settings/filters/SepiaV.xml
 create mode 100644 indra/newview/app_settings/filters/Spotlight.xml
 create mode 100755 indra/newview/app_settings/filters/Video.xml
 delete mode 100644 indra/newview/app_settings/filters/VividV.xml
 delete mode 100644 indra/newview/app_settings/filters/VividYellowV.xml
 delete mode 100644 indra/newview/app_settings/filters/YellowV.xml

diff --git a/indra/newview/app_settings/filters/1970s color.xml b/indra/newview/app_settings/filters/1970s color.xml
new file mode 100644
index 0000000000..0dab2489a0
--- /dev/null
+++ b/indra/newview/app_settings/filters/1970s color.xml	
@@ -0,0 +1,41 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.5</real>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>blend</string>
+            <real>10.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.1</real>
+            <real>0.1</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Black & white.xml b/indra/newview/app_settings/filters/Black & white.xml
new file mode 100644
index 0000000000..101ed8233a
--- /dev/null
+++ b/indra/newview/app_settings/filters/Black & white.xml	
@@ -0,0 +1,21 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.01</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Brightscan.xml b/indra/newview/app_settings/filters/Brightscan.xml
deleted file mode 100755
index 8b10687ef5..0000000000
--- a/indra/newview/app_settings/filters/Brightscan.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.01</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>lines</string>
-            <real>10.0</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>brighten</string>
-            <real>100.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/Grayscale.xml b/indra/newview/app_settings/filters/Grayscale.xml
deleted file mode 100644
index 101ed8233a..0000000000
--- a/indra/newview/app_settings/filters/Grayscale.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.01</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>contrast</string>
-            <real>0.8</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>grayscale</string>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/GreenGray.xml b/indra/newview/app_settings/filters/GreenGray.xml
deleted file mode 100644
index dce5ab3e9e..0000000000
--- a/indra/newview/app_settings/filters/GreenGray.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>colorize</string>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>0.0</real>
-            <real>0.3</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>saturate</string>
-            <real>0.35</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/HLines.xml b/indra/newview/app_settings/filters/HLines.xml
deleted file mode 100644
index ddff4d1977..0000000000
--- a/indra/newview/app_settings/filters/HLines.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>grayscale</string>
-        </array>
-        <array>
-            <string>blend</string>
-            <real>0.0</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>screen</string>
-            <string>line</string>
-            <real>5.0</real>
-            <real>0.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/Heatwave.xml b/indra/newview/app_settings/filters/Heatwave.xml
new file mode 100644
index 0000000000..5c47ca0f84
--- /dev/null
+++ b/indra/newview/app_settings/filters/Heatwave.xml
@@ -0,0 +1,32 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>fade</string>
+            <real>4.0</real>
+            <real>0.5</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>0.4</real>
+            <real>0.0</real>
+            <real>0.2</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Intense.xml b/indra/newview/app_settings/filters/Intense.xml
new file mode 100644
index 0000000000..b77f07a037
--- /dev/null
+++ b/indra/newview/app_settings/filters/Intense.xml
@@ -0,0 +1,8 @@
+<llsd>
+    <array>
+        <array>
+            <string>saturate</string>
+            <real>3.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Jules Verne.xml b/indra/newview/app_settings/filters/Jules Verne.xml
new file mode 100644
index 0000000000..ddff4d1977
--- /dev/null
+++ b/indra/newview/app_settings/filters/Jules Verne.xml	
@@ -0,0 +1,25 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+        <array>
+            <string>blend</string>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>screen</string>
+            <string>line</string>
+            <real>5.0</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Overcast.xml b/indra/newview/app_settings/filters/Overcast.xml
new file mode 100644
index 0000000000..dce5ab3e9e
--- /dev/null
+++ b/indra/newview/app_settings/filters/Overcast.xml
@@ -0,0 +1,24 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.3</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>saturate</string>
+            <real>0.35</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/RedV.xml b/indra/newview/app_settings/filters/RedV.xml
deleted file mode 100644
index 5c47ca0f84..0000000000
--- a/indra/newview/app_settings/filters/RedV.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>contrast</string>
-            <real>0.8</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>fade</string>
-            <real>4.0</real>
-            <real>0.5</real>
-        </array>
-        <array>
-            <string>colorize</string>
-            <real>1.0</real>
-            <real>0.0</real>
-            <real>1.0</real>
-            <real>0.4</real>
-            <real>0.0</real>
-            <real>0.2</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/Saturate30.xml b/indra/newview/app_settings/filters/Saturate30.xml
deleted file mode 100644
index b77f07a037..0000000000
--- a/indra/newview/app_settings/filters/Saturate30.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>saturate</string>
-            <real>3.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/Sepia.xml b/indra/newview/app_settings/filters/Sepia.xml
new file mode 100644
index 0000000000..d26df608b9
--- /dev/null
+++ b/indra/newview/app_settings/filters/Sepia.xml
@@ -0,0 +1,26 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.01</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>fade</string>
+            <real>4.0</real>
+            <real>0.5</real>
+        </array>
+        <array>
+            <string>sepia</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/SepiaV.xml b/indra/newview/app_settings/filters/SepiaV.xml
deleted file mode 100644
index d26df608b9..0000000000
--- a/indra/newview/app_settings/filters/SepiaV.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.01</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>contrast</string>
-            <real>0.8</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>fade</string>
-            <real>4.0</real>
-            <real>0.5</real>
-        </array>
-        <array>
-            <string>sepia</string>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/Spotlight.xml b/indra/newview/app_settings/filters/Spotlight.xml
new file mode 100644
index 0000000000..203130bdee
--- /dev/null
+++ b/indra/newview/app_settings/filters/Spotlight.xml
@@ -0,0 +1,45 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>saturate</string>
+            <real>1.5</real>
+        </array>
+        <array>
+            <string>fade</string>
+            <real>1.0</real>
+            <real>0.25</real>
+        </array>
+        <array>
+            <string>saturate</string>
+            <real>0.8</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>1.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>brighten</string>
+            <real>30</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Video.xml b/indra/newview/app_settings/filters/Video.xml
new file mode 100755
index 0000000000..8b10687ef5
--- /dev/null
+++ b/indra/newview/app_settings/filters/Video.xml
@@ -0,0 +1,23 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.01</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>lines</string>
+            <real>10.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>brighten</string>
+            <real>100.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/VividV.xml b/indra/newview/app_settings/filters/VividV.xml
deleted file mode 100644
index 203130bdee..0000000000
--- a/indra/newview/app_settings/filters/VividV.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>contrast</string>
-            <real>0.8</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>saturate</string>
-            <real>1.5</real>
-        </array>
-        <array>
-            <string>fade</string>
-            <real>1.0</real>
-            <real>0.25</real>
-        </array>
-        <array>
-            <string>saturate</string>
-            <real>0.8</real>
-        </array>
-        <array>
-            <string>contrast</string>
-            <real>1.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>brighten</string>
-            <real>30</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/VividYellowV.xml b/indra/newview/app_settings/filters/VividYellowV.xml
deleted file mode 100644
index 2da27e53c1..0000000000
--- a/indra/newview/app_settings/filters/VividYellowV.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>contrast</string>
-            <real>1.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>fade</string>
-            <real>1.0</real>
-            <real>0.25</real>
-        </array>
-        <array>
-            <string>colorize</string>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>0.3</real>
-            <real>0.2</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>contrast</string>
-            <real>1.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/YellowV.xml b/indra/newview/app_settings/filters/YellowV.xml
deleted file mode 100644
index 0dab2489a0..0000000000
--- a/indra/newview/app_settings/filters/YellowV.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>contrast</string>
-            <real>0.8</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>colorize</string>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>0.5</real>
-            <real>0.0</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>blend</string>
-            <real>10.0</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>colorize</string>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>0.1</real>
-            <real>0.1</real>
-            <real>0.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
index 28e3557e15..47ddecdf38 100644
--- a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
@@ -53,10 +53,6 @@
                  label="No Filter"
                  name="NoFilter"
                  value="NoFilter" />
-                <combo_box.item
-                 label="Gray Scale"
-                 name="GrayScale"
-                 value="GrayScale" />
             </combo_box>
             <panel
                 height="150"
-- 
cgit v1.2.3


From 54ad7de61b5be2014c2e061a4964b7d6620a5dd4 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Mon, 13 Jan 2014 17:01:44 -0800
Subject: ACME-1244 : Introduced llimage/llimagefilter, refactored the filter
 execution code, simplified llimage_libtest filter testing

---
 .../llimage_libtest/llimage_libtest.cpp            | 274 +--------------------
 indra/llimage/CMakeLists.txt                       |   2 +
 indra/llimage/llimagefilter.cpp                    | 269 ++++++++++++++++++++
 indra/llimage/llimagefilter.h                      |  73 ++++++
 4 files changed, 351 insertions(+), 267 deletions(-)
 create mode 100755 indra/llimage/llimagefilter.cpp
 create mode 100755 indra/llimage/llimagefilter.h

diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 2447e00028..d3373a61f2 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -32,6 +32,7 @@
 
 // Linden library includes
 #include "llimage.h"
+#include "llimagefilter.h"
 #include "llimagejpeg.h"
 #include "llimagepng.h"
 #include "llimagebmp.h"
@@ -85,28 +86,8 @@ static const char USAGE[] = "\n"
 " -rev, --reversible\n"
 "        Set the compression to be lossless (reversible in j2c parlance).\n"
 "        Only valid for output j2c images.\n"
-" -f, --filter <name> [<param>]\n"
-"        Apply the filter <name> to the input images using the optional <param> value. Admissible names:\n"
-"        - 'grayscale' converts to grayscale (no param).\n"
-"        - 'sepia' converts to sepia (no param).\n"
-"        - 'saturate' changes color saturation according to <param>: < 1.0 will desaturate, > 1.0 will saturate.\n"
-"        - 'rotate' rotates the color hue according to <param> (in degree, positive value only).\n"
-"        - 'gamma' applies gamma curve <param> to all channels: > 1.0 will darken, < 1.0 will lighten.\n"
-"        - 'colorize' applies a red tint to the image using <param> as an alpha (transparency between 0.0 and 1.0) value.\n"
-"        - 'contrast' modifies the contrast according to <param> : > 1.0 will enhance the contrast, <1.0 will flatten it.\n"
-"        - 'brighten' adds <param> light to the image (<param> between 0 and 255).\n"
-"        - 'darken' substracts <param> light to the image (<param> between 0 and 255).\n"
-"        - 'linearize' optimizes the contrast using the brightness histogram. <param> is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n"
-"        - 'posterize' redistributes the colors between <param> classes per channel (<param> between 2 and 255).\n"
-"        - 'newsscreen' applies a 2D sine screening to the red channel and output to black and white.\n"
-"        - 'horizontalscreen' applies a horizontal screening to the red channel and output to black and white.\n"
-"        - 'verticalscreen' applies a vertical screening to the red channel and output to black and white.\n"
-"        - 'slantedscreen' applies a 45 degrees slanted screening to the red channel and output to black and white.\n"
-"        - Any other value will be interpreted as a file name describing a sequence of filters and parameters to be applied to the input images.\n"
-" -v, --vignette <name> [<feather> <min>]\n"
-"        Apply a circular central vignette <name> to the filter using the optional <feather> and <min> values. Admissible names:\n"
-"        - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n"
-"        - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n"
+" -f, --filter <file>\n"
+"        Apply the filter <file> to the input images.\n"
 " -log, --logmetrics <metric>\n"
 "        Log performance data for <metric>. Results in <metric>.slp\n"
 "        Note: so far, only ImageCompressionTester has been tested.\n"
@@ -120,123 +101,6 @@ static const char USAGE[] = "\n"
 // true when all image loading is done. Used by metric logging thread to know when to stop the thread.
 static bool sAllDone = false;
 
-// Load filter from file
-LLSD load_filter_from_file(const std::string& file_path)
-{
-	//std::cout << "Loading filter settings from : " << file_path << std::endl;
-	llifstream filter_xml(file_path);
-	if (filter_xml.is_open())
-	{
-		// load and parse it
-		LLSD filter_data(LLSD::emptyArray());
-		LLPointer<LLSDParser> parser = new LLSDXMLParser();
-		parser->parse(filter_xml, filter_data, LLSDSerialize::SIZE_UNLIMITED);
-		filter_xml.close();
-		return filter_data;
-	}
-	else
-	{
-		return LLSD();
-	}
-}
-
-// Apply the filter data to the image passed as parameter
-void execute_filter(const LLSD& filter_data, LLPointer<LLImageRaw> raw_image)
-{
-	//std::cout << "Filter : size = " << filter_data.size() << std::endl;
-	for (S32 i = 0; i < filter_data.size(); ++i)
-	{
-        std::string filter_name = filter_data[i][0].asString();
-        // Dump out the filter values (for debug)
-        //std::cout << "Filter : name = " << filter_data[i][0].asString() << ", params = ";
-        //for (S32 j = 1; j < filter_data[i].size(); ++j)
-        //{
-        //    std::cout << filter_data[i][j].asString() << ", ";
-        //}
-        //std::cout << std::endl;
-        
-        // Execute the filter described on this line
-        if (filter_name == "blend")
-        {
-            raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal()));
-        }
-        else if (filter_name == "fade")
-        {
-            raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal()));
-        }
-        else if (filter_name == "lines")
-        {
-            raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal()));
-        }
-        else if (filter_name == "sepia")
-        {
-            raw_image->filterSepia();
-        }
-        else if (filter_name == "grayscale")
-        {
-            raw_image->filterGrayScale();
-        }
-        else if (filter_name == "saturate")
-        {
-            raw_image->filterSaturate((float)(filter_data[i][1].asReal()));
-        }
-        else if (filter_name == "rotate")
-        {
-            raw_image->filterRotate((float)(filter_data[i][1].asReal()));
-        }
-        else if (filter_name == "gamma")
-        {
-            LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal()));
-            raw_image->filterGamma((float)(filter_data[i][1].asReal()),color);
-        }
-        else if (filter_name == "colorize")
-        {
-            LLColor3 color((float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()));
-            LLColor3 alpha((F32)(filter_data[i][4].asReal()),(float)(filter_data[i][5].asReal()),(float)(filter_data[i][6].asReal()));
-            raw_image->filterColorize(color,alpha);
-        }
-        else if (filter_name == "contrast")
-        {
-            LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal()));
-            raw_image->filterContrast((float)(filter_data[i][1].asReal()),color);
-        }
-        else if (filter_name == "brighten")
-        {
-            LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal()));
-            raw_image->filterBrightness((S32)(filter_data[i][1].asReal()),color);
-        }
-        else if (filter_name == "darken")
-        {
-            LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal()));
-            raw_image->filterBrightness((S32)(-filter_data[i][1].asReal()),color);
-        }
-        else if (filter_name == "linearize")
-        {
-            LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal()));
-            raw_image->filterLinearize((float)(filter_data[i][1].asReal()),color);
-        }
-        else if (filter_name == "posterize")
-        {
-            LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal()));
-            raw_image->filterEqualize((S32)(filter_data[i][1].asReal()),color);
-        }
-        else if (filter_name == "screen")
-        {
-            std::string screen_name = filter_data[i][1].asString();
-            EScreenMode mode = SCREEN_MODE_2DSINE;
-            if (screen_name == "2Dsine")
-            {
-                mode = SCREEN_MODE_2DSINE;
-            }
-            else if (screen_name == "line")
-            {
-                mode = SCREEN_MODE_LINE;
-            }
-            raw_image->filterScreen(mode,(S32)(filter_data[i][2].asReal()),(F32)(filter_data[i][3].asReal()));
-        }
-    }
-}
-
 // Create an empty formatted image instance of the correct type from the filename
 LLPointer<LLImageFormatted> create_image(const std::string &filename)
 {
@@ -492,10 +356,6 @@ int main(int argc, char** argv)
 	int levels = 0;
 	bool reversible = false;
     std::string filter_name = "";
-    double filter_param = 0.0;
-    std::string vignette_name = "";
-    double vignette_param_1 = 1.0;
-    double vignette_param_2 = 0.0;
 
 	// Init whatever is necessary
 	ll_init_apr();
@@ -686,53 +546,6 @@ int main(int argc, char** argv)
 				arg += 1;					// Skip that arg now we know it's a valid test name
 				if ((arg + 1) == argc)		// Break out of the loop if we reach the end of the arg list
 					break;
-                // --filter can also have an optional parameter
-                std::string value_str;
-                value_str = argv[arg+1];    // Check the next arg
-                if (value_str[0] != '-')    // If it's not another argument, it's a filter parameter value
-                {
-                    filter_param = atof(value_str.c_str());
-                    arg += 1;					// Skip that arg now we used it as a valid filter param
-                    if ((arg + 1) == argc)		// Break out of the loop if we reach the end of the arg list
-                        break;
-               }
-            }
-		}
-		else if (!strcmp(argv[arg], "--vignette") || !strcmp(argv[arg], "-v"))
-		{
-			// '--vignette' needs to be specified with a named vignette argument
-			if ((arg + 1) < argc)
-			{
-				vignette_name = argv[arg+1];
-			}
-			if (((arg + 1) >= argc) || (vignette_name[0] == '-'))
-			{
-				// We don't have an argument left in the arg list or the next argument is another option
-				std::cout << "No --vignette argument given, no vignette will be applied to filters" << std::endl;
-			}
-			else
-			{
-				arg += 1;					// Skip that arg now we know it's a valid vignette name
-				if ((arg + 1) == argc)		// Break out of the loop if we reach the end of the arg list
-					break;
-                // --vignette can also have optional parameters
-                std::string value_str;
-                value_str = argv[arg+1];    // Check the next arg
-                if (value_str[0] != '-')    // If it's not another argument, it's a vignette parameter value
-                {
-                    vignette_param_1 = atof(value_str.c_str());
-                    arg += 1;					// Skip that arg now we used it as a valid vignette param
-                    if ((arg + 1) == argc)		// Break out of the loop if we reach the end of the arg list
-                        break;
-                    value_str = argv[arg+1];    // Check the next arg
-                    if (value_str[0] != '-')    // If it's not another argument, it's a vignette parameter value
-                    {
-                        vignette_param_2 = atof(value_str.c_str());
-                        arg += 1;					// Skip that arg now we used it as a valid vignette param
-                        if ((arg + 1) == argc)		// Break out of the loop if we reach the end of the arg list
-                            break;
-                    }
-                }
             }
 		}
         else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a"))
@@ -781,85 +594,12 @@ int main(int argc, char** argv)
 			continue;
 		}
         
-        // Set the vignette if any
-        if (vignette_name == "blend")
-        {
-            raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2));
-        }
-        else if (vignette_name == "fade")
-        {
-            raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2));
-        }
-        
-        // Apply filter if any
-        if (filter_name == "sepia")
-        {
-            raw_image->filterSepia();
-        }
-        else if (filter_name == "grayscale")
-        {
-            raw_image->filterGrayScale();
-        }
-        else if (filter_name == "saturate")
-        {
-            raw_image->filterSaturate((float)(filter_param));
-        }
-        else if (filter_name == "rotate")
-        {
-            raw_image->filterRotate((float)(filter_param));
-        }
-        else if (filter_name == "gamma")
-        {
-            raw_image->filterGamma((float)(filter_param),LLColor3::white);
-        }
-        else if (filter_name == "colorize")
-        {
-            // For testing, we just colorize in the red channel, modulate by the alpha passed as a parameter
-            LLColor3 color(1.0,0.0,0.0);
-            LLColor3 alpha((F32)(filter_param),0.0,0.0);
-            raw_image->filterColorize(color,alpha);
-        }
-        else if (filter_name == "contrast")
-        {
-            raw_image->filterContrast((float)(filter_param),LLColor3::white);
-        }
-        else if (filter_name == "brighten")
-        {
-            raw_image->filterBrightness((S32)(filter_param),LLColor3::white);
-        }
-        else if (filter_name == "darken")
-        {
-            raw_image->filterBrightness((S32)(-filter_param),LLColor3::white);
-        }
-        else if (filter_name == "linearize")
-        {
-            raw_image->filterLinearize((float)(filter_param),LLColor3::white);
-        }
-        else if (filter_name == "posterize")
-        {
-            raw_image->filterEqualize((S32)(filter_param),LLColor3::white);
-        }
-        else if (filter_name == "newsscreen")
-        {
-            raw_image->filterScreen(SCREEN_MODE_2DSINE,(S32)(filter_param),0.0);
-        }
-        else if (filter_name == "horizontalscreen")
-        {
-            raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),0.0);
-        }
-        else if (filter_name == "verticalscreen")
-        {
-            raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),90.0);
-        }
-        else if (filter_name == "slantedscreen")
-        {
-            raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),45.0);
-        }
-        else if (filter_name != "")
+        if (filter_name != "")
         {
             // We're interpreting the filter as a filter file name
-            LLSD filter_data = load_filter_from_file(filter_name);
-            execute_filter(filter_data,raw_image);
+            LLImageFilter filter;
+            filter.loadFromFile(filter_name);
+            filter.executeFilter(raw_image);
         }
 
 		// Save file
diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt
index e837b0cac2..293ada7548 100755
--- a/indra/llimage/CMakeLists.txt
+++ b/indra/llimage/CMakeLists.txt
@@ -27,6 +27,7 @@ set(llimage_SOURCE_FILES
     llimage.cpp
     llimagedimensionsinfo.cpp
     llimagedxt.cpp
+    llimagefilter.cpp
     llimagej2c.cpp
     llimagejpeg.cpp
     llimagepng.cpp
@@ -42,6 +43,7 @@ set(llimage_HEADER_FILES
     llimagebmp.h
     llimagedimensionsinfo.h
     llimagedxt.h
+    llimagefilter.h
     llimagej2c.h
     llimagejpeg.h
     llimagepng.h
diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
new file mode 100755
index 0000000000..e2d281e48d
--- /dev/null
+++ b/indra/llimage/llimagefilter.cpp
@@ -0,0 +1,269 @@
+/** 
+ * @file llimagefilter.cpp
+ * @brief Simple Image Filtering.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2014, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llimagefilter.h"
+
+#include "llmath.h"
+#include "v3color.h"
+#include "v4coloru.h"
+#include "m3math.h"
+#include "v3math.h"
+#include "llsdserialize.h"
+
+//---------------------------------------------------------------------------
+// LLImageFilter
+//---------------------------------------------------------------------------
+
+LLImageFilter::LLImageFilter() :
+    mFilterData(LLSD::emptyArray())
+{
+}
+
+LLImageFilter::~LLImageFilter()
+{
+}
+
+/*
+ " -f, --filter <name> [<param>]\n"
+ "        Apply the filter <name> to the input images using the optional <param> value. Admissible names:\n"
+ "        - 'grayscale' converts to grayscale (no param).\n"
+ "        - 'sepia' converts to sepia (no param).\n"
+ "        - 'saturate' changes color saturation according to <param>: < 1.0 will desaturate, > 1.0 will saturate.\n"
+ "        - 'rotate' rotates the color hue according to <param> (in degree, positive value only).\n"
+ "        - 'gamma' applies gamma curve <param> to all channels: > 1.0 will darken, < 1.0 will lighten.\n"
+ "        - 'colorize' applies a red tint to the image using <param> as an alpha (transparency between 0.0 and 1.0) value.\n"
+ "        - 'contrast' modifies the contrast according to <param> : > 1.0 will enhance the contrast, <1.0 will flatten it.\n"
+ "        - 'brighten' adds <param> light to the image (<param> between 0 and 255).\n"
+ "        - 'darken' substracts <param> light to the image (<param> between 0 and 255).\n"
+ "        - 'linearize' optimizes the contrast using the brightness histogram. <param> is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n"
+ "        - 'posterize' redistributes the colors between <param> classes per channel (<param> between 2 and 255).\n"
+ "        - 'newsscreen' applies a 2D sine screening to the red channel and output to black and white.\n"
+ "        - 'horizontalscreen' applies a horizontal screening to the red channel and output to black and white.\n"
+ "        - 'verticalscreen' applies a vertical screening to the red channel and output to black and white.\n"
+ "        - 'slantedscreen' applies a 45 degrees slanted screening to the red channel and output to black and white.\n"
+ "        - Any other value will be interpreted as a file name describing a sequence of filters and parameters to be applied to the input images.\n"
+ " -v, --vignette <name> [<feather> <min>]\n"
+ "        Apply a circular central vignette <name> to the filter using the optional <feather> and <min> values. Admissible names:\n"
+ "        - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n"
+ "        - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n"
+
+ // Set the vignette if any
+ if (vignette_name == "blend")
+ {
+ raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2));
+ }
+ else if (vignette_name == "fade")
+ {
+ raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2));
+ }
+ 
+ // Apply filter if any
+ if (filter_name == "sepia")
+ {
+ raw_image->filterSepia();
+ }
+ else if (filter_name == "grayscale")
+ {
+ raw_image->filterGrayScale();
+ }
+ else if (filter_name == "saturate")
+ {
+ raw_image->filterSaturate((float)(filter_param));
+ }
+ else if (filter_name == "rotate")
+ {
+ raw_image->filterRotate((float)(filter_param));
+ }
+ else if (filter_name == "gamma")
+ {
+ raw_image->filterGamma((float)(filter_param),LLColor3::white);
+ }
+ else if (filter_name == "colorize")
+ {
+ // For testing, we just colorize in the red channel, modulate by the alpha passed as a parameter
+ LLColor3 color(1.0,0.0,0.0);
+ LLColor3 alpha((F32)(filter_param),0.0,0.0);
+ raw_image->filterColorize(color,alpha);
+ }
+ else if (filter_name == "contrast")
+ {
+ raw_image->filterContrast((float)(filter_param),LLColor3::white);
+ }
+ else if (filter_name == "brighten")
+ {
+ raw_image->filterBrightness((S32)(filter_param),LLColor3::white);
+ }
+ else if (filter_name == "darken")
+ {
+ raw_image->filterBrightness((S32)(-filter_param),LLColor3::white);
+ }
+ else if (filter_name == "linearize")
+ {
+ raw_image->filterLinearize((float)(filter_param),LLColor3::white);
+ }
+ else if (filter_name == "posterize")
+ {
+ raw_image->filterEqualize((S32)(filter_param),LLColor3::white);
+ }
+ else if (filter_name == "newsscreen")
+ {
+ raw_image->filterScreen(SCREEN_MODE_2DSINE,(S32)(filter_param),0.0);
+ }
+ else if (filter_name == "horizontalscreen")
+ {
+ raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),0.0);
+ }
+ else if (filter_name == "verticalscreen")
+ {
+ raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),90.0);
+ }
+ else if (filter_name == "slantedscreen")
+ {
+ raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),45.0);
+ }
+ 
+ */
+
+// Load filter from file
+void LLImageFilter::loadFromFile(const std::string& file_path)
+{
+	//std::cout << "Loading filter settings from : " << file_path << std::endl;
+	llifstream filter_xml(file_path);
+	if (filter_xml.is_open())
+	{
+		// Load and parse the file
+		LLPointer<LLSDParser> parser = new LLSDXMLParser();
+		parser->parse(filter_xml, mFilterData, LLSDSerialize::SIZE_UNLIMITED);
+		filter_xml.close();
+	}
+	else
+	{
+        // File couldn't be open, reset the filter data
+		mFilterData = LLSD();
+	}
+}
+
+// Apply the filter data to the image passed as parameter
+void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
+{
+	//std::cout << "Filter : size = " << mFilterData.size() << std::endl;
+	for (S32 i = 0; i < mFilterData.size(); ++i)
+	{
+        std::string filter_name = mFilterData[i][0].asString();
+        // Dump out the filter values (for debug)
+        //std::cout << "Filter : name = " << mFilterData[i][0].asString() << ", params = ";
+        //for (S32 j = 1; j < mFilterData[i].size(); ++j)
+        //{
+        //    std::cout << mFilterData[i][j].asString() << ", ";
+        //}
+        //std::cout << std::endl;
+        
+        // Execute the filter described on this line
+        if (filter_name == "blend")
+        {
+            raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()));
+        }
+        else if (filter_name == "fade")
+        {
+            raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()));
+        }
+        else if (filter_name == "lines")
+        {
+            raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()));
+        }
+        else if (filter_name == "sepia")
+        {
+            raw_image->filterSepia();
+        }
+        else if (filter_name == "grayscale")
+        {
+            raw_image->filterGrayScale();
+        }
+        else if (filter_name == "saturate")
+        {
+            raw_image->filterSaturate((float)(mFilterData[i][1].asReal()));
+        }
+        else if (filter_name == "rotate")
+        {
+            raw_image->filterRotate((float)(mFilterData[i][1].asReal()));
+        }
+        else if (filter_name == "gamma")
+        {
+            LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+            raw_image->filterGamma((float)(mFilterData[i][1].asReal()),color);
+        }
+        else if (filter_name == "colorize")
+        {
+            LLColor3 color((float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()));
+            LLColor3 alpha((F32)(mFilterData[i][4].asReal()),(float)(mFilterData[i][5].asReal()),(float)(mFilterData[i][6].asReal()));
+            raw_image->filterColorize(color,alpha);
+        }
+        else if (filter_name == "contrast")
+        {
+            LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+            raw_image->filterContrast((float)(mFilterData[i][1].asReal()),color);
+        }
+        else if (filter_name == "brighten")
+        {
+            LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+            raw_image->filterBrightness((S32)(mFilterData[i][1].asReal()),color);
+        }
+        else if (filter_name == "darken")
+        {
+            LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+            raw_image->filterBrightness((S32)(-mFilterData[i][1].asReal()),color);
+        }
+        else if (filter_name == "linearize")
+        {
+            LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+            raw_image->filterLinearize((float)(mFilterData[i][1].asReal()),color);
+        }
+        else if (filter_name == "posterize")
+        {
+            LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+            raw_image->filterEqualize((S32)(mFilterData[i][1].asReal()),color);
+        }
+        else if (filter_name == "screen")
+        {
+            std::string screen_name = mFilterData[i][1].asString();
+            EScreenMode mode = SCREEN_MODE_2DSINE;
+            if (screen_name == "2Dsine")
+            {
+                mode = SCREEN_MODE_2DSINE;
+            }
+            else if (screen_name == "line")
+            {
+                mode = SCREEN_MODE_LINE;
+            }
+            raw_image->filterScreen(mode,(S32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal()));
+        }
+    }
+}
+
+
+//============================================================================
diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h
new file mode 100755
index 0000000000..5598fa69f5
--- /dev/null
+++ b/indra/llimage/llimagefilter.h
@@ -0,0 +1,73 @@
+/** 
+ * @file llimagefilter.h
+ * @brief Simple Image Filtering.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2014, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLIMAGEFILTER_H
+#define LL_LLIMAGEFILTER_H
+
+#include "llimage.h"
+
+/*
+class LLImageRaw;
+class LLColor4U;
+class LLColor3;
+class LLMatrix3;
+
+typedef enum e_vignette_mode
+{
+	VIGNETTE_MODE_NONE  = 0,
+	VIGNETTE_MODE_BLEND = 1,
+	VIGNETTE_MODE_FADE  = 2
+} EVignetteMode;
+
+typedef enum e_vignette_type
+{
+	VIGNETTE_TYPE_CENTER = 0,
+	VIGNETTE_TYPE_LINES  = 1
+} EVignetteType;
+
+typedef enum e_screen_mode
+{
+	SCREEN_MODE_2DSINE   = 0,
+	SCREEN_MODE_LINE     = 1
+} EScreenMode;
+*/
+//============================================================================
+// Image Filter 
+
+class LLImageFilter
+{
+public:
+    LLImageFilter();
+    ~LLImageFilter();
+    
+    void loadFromFile(const std::string& file_path);
+    void executeFilter(LLPointer<LLImageRaw> raw_image);
+private:
+    LLSD mFilterData;
+};
+
+
+#endif
-- 
cgit v1.2.3


From d972efa64c5877c611f9ca583483978dca3c6768 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Mon, 13 Jan 2014 17:56:38 -0800
Subject: ACME-1244 : WIP : Execute filters in Flickr panel. Testable but code
 beeds clean up.

---
 indra/newview/llfloaterflickr.cpp       |  7 +++----
 indra/newview/llimagefiltersmanager.cpp |  9 ++++++++-
 indra/newview/llimagefiltersmanager.h   |  1 +
 indra/newview/llsnapshotlivepreview.cpp | 24 +++++++++++++++++-------
 indra/newview/llsnapshotlivepreview.h   |  6 +++---
 5 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 8395c0db5a..cff57bfa13 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -361,13 +361,12 @@ void LLFlickrPhotoPanel::updateResolution(BOOL do_update)
         // Merov : 
         // Get the old filter, compare to the current one "filter_name" and set if changed
         // If changed, also force the updateSnapshot() here under
-        S32 original_filter = previewp->getFilter();
-        S32 filter = ("Gray Scale" == filter_name ? 1 : 0);
+        std::string original_filter = previewp->getFilter();
 		
-		if ((original_width != width) || (original_height != height) || (original_filter != filter))
+		if ((original_width != width) || (original_height != height) || (original_filter != filter_name))
 		{
 			previewp->setSize(width, height);
-            previewp->setFilter(filter);
+            previewp->setFilter(filter_name);
 
 			// hide old preview as the aspect ratio could be wrong
 			lldebugs << "updating thumbnail" << llendl;
diff --git a/indra/newview/llimagefiltersmanager.cpp b/indra/newview/llimagefiltersmanager.cpp
index 888e5ec5dd..14177b4f05 100644
--- a/indra/newview/llimagefiltersmanager.cpp
+++ b/indra/newview/llimagefiltersmanager.cpp
@@ -85,6 +85,13 @@ void LLImageFiltersManager::loadFiltersFromDir(const std::string& dir)
 	}
 }
 
-
+std::string LLImageFiltersManager::getFilterPath(const std::string& filter_name)
+{
+    // *TODO : we should store (filter name, path) in a std::map
+    std::string file = filter_name + ".xml";
+    std::string dir = getSysDir();
+    std::string path = gDirUtilp->add(dir, file);
+    return path;
+}
 
 //============================================================================
diff --git a/indra/newview/llimagefiltersmanager.h b/indra/newview/llimagefiltersmanager.h
index e916dc7187..5591e14a41 100644
--- a/indra/newview/llimagefiltersmanager.h
+++ b/indra/newview/llimagefiltersmanager.h
@@ -54,6 +54,7 @@ public:
     //LLSD loadFilter(const std::string& filter_name);
     //void executeFilter(const LLSD& filter_data, LLPointer<LLImageRaw> raw_image);
     const std::vector<std::string> &getFiltersList() const { return mFiltersList; }
+    std::string getFilterPath(const std::string& filter_name);
   
 protected:
 private:
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 2931178ace..c38798bbea 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -37,6 +37,8 @@
 #include "llfloaterfacebook.h"
 #include "llfloaterflickr.h"
 #include "llfloatertwitter.h"
+#include "llimagefilter.h"
+#include "llimagefiltersmanager.h"
 #include "llimagebmp.h"
 #include "llimagej2c.h"
 #include "llimagejpeg.h"
@@ -90,7 +92,7 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param
 	mCameraRot(LLViewerCamera::getInstance()->getQuaternion()),
 	mSnapshotActive(FALSE),
 	mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR),
-    mFilterType(0)
+    mFilterName("")
 {
 	setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality"));
 	mSnapshotDelayTimer.setTimerExpirySec(0.0f);
@@ -586,10 +588,14 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
 	if(raw)
 	{
 		raw->expandToPowerOfTwo();
-        // Merov : Filter also the thumbnail?
-        if (getFilter() == 1)
+        // Filter the thumbnail
+        if (getFilter() != "")
         {
-            raw->filterGrayScale();
+            LLImageFilter filter;
+            std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter());
+            filter.loadFromFile(filter_path);
+            filter.executeFilter(raw);
+            //raw->filterGrayScale();
         }
 		mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
 		mThumbnailUpToDate = TRUE ;
@@ -695,10 +701,14 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 		}
 		else
 		{
-            // Merov : Time to apply the filter to mPreviewImage!!!
-            if (previewp->getFilter() == 1)
+            // Apply the filter to mPreviewImage
+            if (previewp->getFilter() != "")
             {
-                previewp->mPreviewImage->filterGrayScale();
+                LLImageFilter filter;
+                std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(previewp->getFilter());
+                filter.loadFromFile(filter_path);
+                filter.executeFilter(previewp->mPreviewImage);
+                //previewp->mPreviewImage->filterGrayScale();
             }
             
 			// delete any existing image
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index d5ae3b491b..6addc87de2 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -95,8 +95,8 @@ public:
 	void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; }
 	bool setSnapshotQuality(S32 quality, bool set_by_user = true);
 	void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
-    void setFilter(S32 filter) { mFilterType = filter; }
-    S32  getFilter() { return mFilterType; }
+    void setFilter(std::string filter_name) { mFilterName = filter_name; }
+    std::string  getFilter() { return mFilterName; }
 	void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f);
 	void saveWeb();
 	void saveTexture();
@@ -156,7 +156,7 @@ private:
 	LLQuaternion				mCameraRot;
 	BOOL						mSnapshotActive;
 	LLViewerWindow::ESnapshotType mSnapshotBufferType;
-    S32                         mFilterType; // *TODO: eventually use a string and a named filter
+    std::string                 mFilterName;
 
 public:
 	static std::set<LLSnapshotLivePreview*> sList;
-- 
cgit v1.2.3


From 7cc64a09a3ca9211354427206f04d157c9ac30a2 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 14 Jan 2014 21:01:51 -0800
Subject: ACME-1236 : Refactor filters and vignette into llimagefilter, add
 example filters to llimage_libtest

---
 .../llimage_libtest/1970colorize.xml               |  41 ++
 .../integration_tests/llimage_libtest/brighten.xml |  11 +
 .../integration_tests/llimage_libtest/colorize.xml |  20 +
 .../integration_tests/llimage_libtest/contrast.xml |  18 +
 indra/integration_tests/llimage_libtest/darken.xml |  11 +
 indra/integration_tests/llimage_libtest/gamma.xml  |  18 +
 .../llimage_libtest/grayscale.xml                  |  14 +
 .../llimage_libtest/horizontalscreen.xml           |  25 +
 .../llimage_libtest/linearize.xml                  |  11 +
 .../llimage_libtest/newsscreen.xml                 |  25 +
 .../llimage_libtest/posterize.xml                  |  18 +
 .../llimage_libtest/rotatecolors180.xml            |   8 +
 .../integration_tests/llimage_libtest/saturate.xml |   8 +
 indra/integration_tests/llimage_libtest/sepia.xml  |  14 +
 .../llimage_libtest/slantedscreen.xml              |  25 +
 .../llimage_libtest/spotlight.xml                  |  45 ++
 .../llimage_libtest/verticalscreen.xml             |  25 +
 indra/integration_tests/llimage_libtest/video.xml  |  23 +
 indra/llimage/llimage.cpp                          | 527 +----------------
 indra/llimage/llimage.h                            |  61 --
 indra/llimage/llimagefilter.cpp                    | 641 ++++++++++++++++++---
 indra/llimage/llimagefilter.h                      |  50 +-
 22 files changed, 956 insertions(+), 683 deletions(-)
 create mode 100644 indra/integration_tests/llimage_libtest/1970colorize.xml
 create mode 100755 indra/integration_tests/llimage_libtest/brighten.xml
 create mode 100644 indra/integration_tests/llimage_libtest/colorize.xml
 create mode 100644 indra/integration_tests/llimage_libtest/contrast.xml
 create mode 100755 indra/integration_tests/llimage_libtest/darken.xml
 create mode 100644 indra/integration_tests/llimage_libtest/gamma.xml
 create mode 100644 indra/integration_tests/llimage_libtest/grayscale.xml
 create mode 100644 indra/integration_tests/llimage_libtest/horizontalscreen.xml
 create mode 100755 indra/integration_tests/llimage_libtest/linearize.xml
 create mode 100755 indra/integration_tests/llimage_libtest/newsscreen.xml
 create mode 100755 indra/integration_tests/llimage_libtest/posterize.xml
 create mode 100644 indra/integration_tests/llimage_libtest/rotatecolors180.xml
 create mode 100644 indra/integration_tests/llimage_libtest/saturate.xml
 create mode 100644 indra/integration_tests/llimage_libtest/sepia.xml
 create mode 100644 indra/integration_tests/llimage_libtest/slantedscreen.xml
 create mode 100644 indra/integration_tests/llimage_libtest/spotlight.xml
 create mode 100644 indra/integration_tests/llimage_libtest/verticalscreen.xml
 create mode 100755 indra/integration_tests/llimage_libtest/video.xml

diff --git a/indra/integration_tests/llimage_libtest/1970colorize.xml b/indra/integration_tests/llimage_libtest/1970colorize.xml
new file mode 100644
index 0000000000..0dab2489a0
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/1970colorize.xml
@@ -0,0 +1,41 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.5</real>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>blend</string>
+            <real>10.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.1</real>
+            <real>0.1</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/brighten.xml b/indra/integration_tests/llimage_libtest/brighten.xml
new file mode 100755
index 0000000000..d17b96d2d7
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/brighten.xml
@@ -0,0 +1,11 @@
+<llsd>
+    <array>
+        <array>
+            <string>brighten</string>
+            <real>50.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/colorize.xml b/indra/integration_tests/llimage_libtest/colorize.xml
new file mode 100644
index 0000000000..18c6cd3425
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/colorize.xml
@@ -0,0 +1,20 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.2</real>
+            <real>0.0</real>
+            <real>0.2</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/contrast.xml b/indra/integration_tests/llimage_libtest/contrast.xml
new file mode 100644
index 0000000000..8dcdd1a9a9
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/contrast.xml
@@ -0,0 +1,18 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>1.5</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/darken.xml b/indra/integration_tests/llimage_libtest/darken.xml
new file mode 100755
index 0000000000..8d110452e9
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/darken.xml
@@ -0,0 +1,11 @@
+<llsd>
+    <array>
+        <array>
+            <string>darken</string>
+            <real>50.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/gamma.xml b/indra/integration_tests/llimage_libtest/gamma.xml
new file mode 100644
index 0000000000..7505a03027
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/gamma.xml
@@ -0,0 +1,18 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>gamma</string>
+            <real>1.5</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/grayscale.xml b/indra/integration_tests/llimage_libtest/grayscale.xml
new file mode 100644
index 0000000000..984312c4fd
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/grayscale.xml
@@ -0,0 +1,14 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/horizontalscreen.xml b/indra/integration_tests/llimage_libtest/horizontalscreen.xml
new file mode 100644
index 0000000000..ddff4d1977
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/horizontalscreen.xml
@@ -0,0 +1,25 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+        <array>
+            <string>blend</string>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>screen</string>
+            <string>line</string>
+            <real>5.0</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/linearize.xml b/indra/integration_tests/llimage_libtest/linearize.xml
new file mode 100755
index 0000000000..23d0290e07
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/linearize.xml
@@ -0,0 +1,11 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/newsscreen.xml b/indra/integration_tests/llimage_libtest/newsscreen.xml
new file mode 100755
index 0000000000..8247c34500
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/newsscreen.xml
@@ -0,0 +1,25 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+        <array>
+            <string>blend</string>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>screen</string>
+            <string>2Dsine</string>
+            <real>5.0</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/posterize.xml b/indra/integration_tests/llimage_libtest/posterize.xml
new file mode 100755
index 0000000000..f026278f9e
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/posterize.xml
@@ -0,0 +1,18 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>posterize</string>
+            <real>10.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/rotatecolors180.xml b/indra/integration_tests/llimage_libtest/rotatecolors180.xml
new file mode 100644
index 0000000000..e25029720f
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/rotatecolors180.xml
@@ -0,0 +1,8 @@
+<llsd>
+    <array>
+        <array>
+            <string>rotate</string>
+            <real>180.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/saturate.xml b/indra/integration_tests/llimage_libtest/saturate.xml
new file mode 100644
index 0000000000..b77f07a037
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/saturate.xml
@@ -0,0 +1,8 @@
+<llsd>
+    <array>
+        <array>
+            <string>saturate</string>
+            <real>3.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/sepia.xml b/indra/integration_tests/llimage_libtest/sepia.xml
new file mode 100644
index 0000000000..0304ead015
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/sepia.xml
@@ -0,0 +1,14 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>sepia</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/slantedscreen.xml b/indra/integration_tests/llimage_libtest/slantedscreen.xml
new file mode 100644
index 0000000000..63ad01d51d
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/slantedscreen.xml
@@ -0,0 +1,25 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+        <array>
+            <string>blend</string>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>screen</string>
+            <string>line</string>
+            <real>5.0</real>
+            <real>45.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/spotlight.xml b/indra/integration_tests/llimage_libtest/spotlight.xml
new file mode 100644
index 0000000000..203130bdee
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/spotlight.xml
@@ -0,0 +1,45 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>saturate</string>
+            <real>1.5</real>
+        </array>
+        <array>
+            <string>fade</string>
+            <real>1.0</real>
+            <real>0.25</real>
+        </array>
+        <array>
+            <string>saturate</string>
+            <real>0.8</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>1.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>brighten</string>
+            <real>30</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/verticalscreen.xml b/indra/integration_tests/llimage_libtest/verticalscreen.xml
new file mode 100644
index 0000000000..71e48df656
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/verticalscreen.xml
@@ -0,0 +1,25 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+        <array>
+            <string>blend</string>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>screen</string>
+            <string>line</string>
+            <real>5.0</real>
+            <real>90.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/video.xml b/indra/integration_tests/llimage_libtest/video.xml
new file mode 100755
index 0000000000..8b10687ef5
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/video.xml
@@ -0,0 +1,23 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.01</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>lines</string>
+            <real>10.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>brighten</string>
+            <real>100.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 3105fe3746..7981ca7364 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -98,14 +98,7 @@ LLImageBase::LLImageBase()
 	  mHeight(0),
 	  mComponents(0),
 	  mBadBufferAllocation(false),
-	  mAllowOverSize(false),
-      mHistoRed(NULL),
-      mHistoGreen(NULL),
-      mHistoBlue(NULL),
-      mHistoBrightness(NULL),
-      mVignetteMode(VIGNETTE_MODE_NONE),
-      mVignetteGamma(1.0),
-      mVignetteMin(0.0)
+	  mAllowOverSize(false)
 {
 }
 
@@ -113,10 +106,6 @@ LLImageBase::LLImageBase()
 LLImageBase::~LLImageBase()
 {
 	deleteData(); // virtual
-    ll_aligned_free_16(mHistoRed);
-    ll_aligned_free_16(mHistoGreen);
-    ll_aligned_free_16(mHistoBlue);
-    ll_aligned_free_16(mHistoBrightness);
 }
 
 //static
@@ -947,520 +936,6 @@ BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
 	return TRUE ;
 }
 
-// Filter Operations
-void LLImageRaw::filterGrayScale()
-{
-    LLMatrix3 gray_scale;
-    LLVector3 luminosity(0.2125, 0.7154, 0.0721);
-    gray_scale.setRows(luminosity, luminosity, luminosity);
-    gray_scale.transpose();
-    colorTransform(gray_scale);
-}
-
-void LLImageRaw::filterSepia()
-{
-    LLMatrix3 sepia;
-    sepia.setRows(LLVector3(0.3588, 0.7044, 0.1368),
-                  LLVector3(0.2990, 0.5870, 0.1140),
-                  LLVector3(0.2392, 0.4696, 0.0912));
-    sepia.transpose();
-    colorTransform(sepia);
-}
-
-void LLImageRaw::filterSaturate(F32 saturation)
-{
-    // Matrix to Lij
-    LLMatrix3 r_a;
-    LLMatrix3 r_b;
-
-    // 45 degre rotation around z
-    r_a.setRows(LLVector3( OO_SQRT2,  OO_SQRT2, 0.0),
-                LLVector3(-OO_SQRT2,  OO_SQRT2, 0.0),
-                LLVector3( 0.0,       0.0,      1.0));
-    // 54.73 degre rotation around y
-    float oo_sqrt3 = 1.0f / F_SQRT3;
-    float sin_54 = F_SQRT2 * oo_sqrt3;
-    r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54),
-                LLVector3(0.0,      1.0,  0.0),
-                LLVector3(sin_54,   0.0,  oo_sqrt3));
-
-    // Coordinate conversion
-    LLMatrix3 Lij = r_b * r_a;
-    LLMatrix3 Lij_inv = Lij;
-    Lij_inv.transpose();
-    
-    // Local saturation transform
-    LLMatrix3 s;
-    s.setRows(LLVector3(saturation, 0.0,  0.0),
-              LLVector3(0.0,  saturation, 0.0),
-              LLVector3(0.0,        0.0,  1.0));
-
-    // Global saturation transform
-    LLMatrix3 transfo = Lij_inv * s * Lij;
-    colorTransform(transfo);
-}
-
-void LLImageRaw::filterRotate(F32 angle)
-{
-    // Matrix to Lij
-    LLMatrix3 r_a;
-    LLMatrix3 r_b;
-    
-    // 45 degre rotation around z
-    r_a.setRows(LLVector3( OO_SQRT2,  OO_SQRT2, 0.0),
-                LLVector3(-OO_SQRT2,  OO_SQRT2, 0.0),
-                LLVector3( 0.0,       0.0,      1.0));
-    // 54.73 degre rotation around y
-    float oo_sqrt3 = 1.0f / F_SQRT3;
-    float sin_54 = F_SQRT2 * oo_sqrt3;
-    r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54),
-                LLVector3(0.0,      1.0,  0.0),
-                LLVector3(sin_54,   0.0,  oo_sqrt3));
-    
-    // Coordinate conversion
-    LLMatrix3 Lij = r_b * r_a;
-    LLMatrix3 Lij_inv = Lij;
-    Lij_inv.transpose();
-    
-    // Local color rotation transform
-    LLMatrix3 r;
-    angle *= DEG_TO_RAD;
-    r.setRows(LLVector3( cosf(angle), sinf(angle), 0.0),
-              LLVector3(-sinf(angle), cosf(angle), 0.0),
-              LLVector3( 0.0,         0.0,         1.0));
-    
-    // Global color rotation transform
-    LLMatrix3 transfo = Lij_inv * r * Lij;
-    colorTransform(transfo);
-}
-
-void LLImageRaw::filterGamma(F32 gamma, const LLColor3& alpha)
-{
-    U8 gamma_red_lut[256];
-    U8 gamma_green_lut[256];
-    U8 gamma_blue_lut[256];
-    
-    for (S32 i = 0; i < 256; i++)
-    {
-        F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,gamma)));
-        // Blend in with alpha values
-        gamma_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * 255.0 * gamma_i);
-        gamma_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * 255.0 * gamma_i);
-        gamma_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * 255.0 * gamma_i);
-    }
-    
-    colorCorrect(gamma_red_lut,gamma_green_lut,gamma_blue_lut);
-}
-
-void LLImageRaw::filterLinearize(F32 tail, const LLColor3& alpha)
-{
-    // Get the histogram
-    U32* histo = getBrightnessHistogram();
-    
-    // Compute cumulated histogram
-    U32 cumulated_histo[256];
-    cumulated_histo[0] = histo[0];
-    for (S32 i = 1; i < 256; i++)
-    {
-        cumulated_histo[i] = cumulated_histo[i-1] + histo[i];
-    }
-    
-    // Compute min and max counts minus tail
-    tail = llclampf(tail);
-    S32 total = cumulated_histo[255];
-    S32 min_c = (S32)((F32)(total) * tail);
-    S32 max_c = (S32)((F32)(total) * (1.0 - tail));
-    
-    // Find min and max values
-    S32 min_v = 0;
-    while (cumulated_histo[min_v] < min_c)
-    {
-        min_v++;
-    }
-    S32 max_v = 255;
-    while (cumulated_histo[max_v] > max_c)
-    {
-        max_v--;
-    }
-    
-    // Compute linear lookup table
-    U8 linear_red_lut[256];
-    U8 linear_green_lut[256];
-    U8 linear_blue_lut[256];
-    if (max_v == min_v)
-    {
-        // Degenerated binary split case
-        for (S32 i = 0; i < 256; i++)
-        {
-            U8 value_i = (i < min_v ? 0 : 255);
-            // Blend in with alpha values
-            linear_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
-            linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
-            linear_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
-        }
-    }
-    else
-    {
-        // Linearize between min and max
-        F32 slope = 255.0 / (F32)(max_v - min_v);
-        F32 translate = -min_v * slope;
-        for (S32 i = 0; i < 256; i++)
-        {
-            U8 value_i = (U8)(llclampb((S32)(slope*i + translate)));
-            // Blend in with alpha values
-            linear_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
-            linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
-            linear_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
-        }
-    }
-    
-    // Apply lookup table
-    colorCorrect(linear_red_lut,linear_green_lut,linear_blue_lut);
-}
-
-void LLImageRaw::filterEqualize(S32 nb_classes, const LLColor3& alpha)
-{
-    // Regularize the parameter: must be between 2 and 255
-    nb_classes = llmax(nb_classes,2);
-    nb_classes = llclampb(nb_classes);
-    
-    // Get the histogram
-    U32* histo = getBrightnessHistogram();
-    
-    // Compute cumulated histogram
-    U32 cumulated_histo[256];
-    cumulated_histo[0] = histo[0];
-    for (S32 i = 1; i < 256; i++)
-    {
-        cumulated_histo[i] = cumulated_histo[i-1] + histo[i];
-    }
-    
-    // Compute deltas
-    S32 total = cumulated_histo[255];
-    S32 delta_count = total / nb_classes;
-    S32 current_count = delta_count;
-    S32 delta_value = 256 / (nb_classes - 1);
-    S32 current_value = 0;
-    
-    // Compute equalized lookup table
-    U8 equalize_red_lut[256];
-    U8 equalize_green_lut[256];
-    U8 equalize_blue_lut[256];
-    for (S32 i = 0; i < 256; i++)
-    {
-        // Blend in current_value with alpha values
-        equalize_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * current_value);
-        equalize_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * current_value);
-        equalize_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * current_value);
-        if (cumulated_histo[i] >= current_count)
-        {
-            current_count += delta_count;
-            current_value += delta_value;
-            current_value = llclampb(current_value);
-        }
-    }
-
-    // Apply lookup table
-    colorCorrect(equalize_red_lut,equalize_green_lut,equalize_blue_lut);
-}
-
-void LLImageRaw::filterColorize(const LLColor3& color, const LLColor3& alpha)
-{
-    U8 red_lut[256];
-    U8 green_lut[256];
-    U8 blue_lut[256];
-    
-    F32 red_composite   =  255.0 * alpha.mV[0] * color.mV[0];
-    F32 green_composite =  255.0 * alpha.mV[1] * color.mV[1];
-    F32 blue_composite  =  255.0 * alpha.mV[2] * color.mV[2];
-    
-    for (S32 i = 0; i < 256; i++)
-    {
-        red_lut[i]   = (U8)(llclampb((S32)((1.0 - alpha.mV[0]) * (F32)(i) + red_composite)));
-        green_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[1]) * (F32)(i) + green_composite)));
-        blue_lut[i]  = (U8)(llclampb((S32)((1.0 - alpha.mV[2]) * (F32)(i) + blue_composite)));
-    }
-    
-    colorCorrect(red_lut,green_lut,blue_lut);
-}
-
-void LLImageRaw::filterContrast(F32 slope, const LLColor3& alpha)
-{
-    U8 contrast_red_lut[256];
-    U8 contrast_green_lut[256];
-    U8 contrast_blue_lut[256];
-    
-    F32 translate = 128.0 * (1.0 - slope);
-    
-    for (S32 i = 0; i < 256; i++)
-    {
-        U8 value_i = (U8)(llclampb((S32)(slope*i + translate)));
-        // Blend in with alpha values
-        contrast_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
-        contrast_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
-        contrast_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
-    }
-    
-    colorCorrect(contrast_red_lut,contrast_green_lut,contrast_blue_lut);
-}
-
-void LLImageRaw::filterBrightness(S32 add, const LLColor3& alpha)
-{
-    U8 brightness_red_lut[256];
-    U8 brightness_green_lut[256];
-    U8 brightness_blue_lut[256];
-    
-    for (S32 i = 0; i < 256; i++)
-    {
-        U8 value_i = (U8)(llclampb((S32)((S32)(i) + add)));
-        // Blend in with alpha values
-        brightness_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
-        brightness_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
-        brightness_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
-    }
-    
-    colorCorrect(brightness_red_lut,brightness_green_lut,brightness_blue_lut);
-}
-
-// Filter Primitives
-void LLImageRaw::colorTransform(const LLMatrix3 &transform)
-{
-	const S32 components = getComponents();
-	llassert( components >= 1 && components <= 4 );
-    
-	S32 width  = getWidth();
-    S32 height = getHeight();
-    
-	U8* dst_data = getData();
-	for (S32 j = 0; j < height; j++)
-	{
-        for (S32 i = 0; i < width; i++)
-        {
-            LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE]));
-            LLVector3 dst = src * transform;
-            dst.clamp(0.0f,255.0f);
-            if (mVignetteMode == VIGNETTE_MODE_NONE)
-            {
-                dst_data[VRED]   = dst.mV[VRED];
-                dst_data[VGREEN] = dst.mV[VGREEN];
-                dst_data[VBLUE]  = dst.mV[VBLUE];
-            }
-            else
-            {
-                F32 alpha = getVignetteAlpha(i,j);
-                if (mVignetteMode == VIGNETTE_MODE_BLEND)
-                {
-                    // Blends with the source image on the edges
-                    F32 inv_alpha = 1.0 - alpha;
-                    dst_data[VRED]   = inv_alpha * src.mV[VRED]   + alpha * dst.mV[VRED];
-                    dst_data[VGREEN] = inv_alpha * src.mV[VGREEN] + alpha * dst.mV[VGREEN];
-                    dst_data[VBLUE]  = inv_alpha * src.mV[VBLUE]  + alpha * dst.mV[VBLUE];
-                }
-                else // VIGNETTE_MODE_FADE
-                {
-                    // Fade to black on the edges
-                    dst_data[VRED]   = alpha * dst.mV[VRED];
-                    dst_data[VGREEN] = alpha * dst.mV[VGREEN];
-                    dst_data[VBLUE]  = alpha * dst.mV[VBLUE];
-                }
-            }
-            dst_data += components;
-        }
-	}
-}
-
-void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue)
-{
-	const S32 components = getComponents();
-	llassert( components >= 1 && components <= 4 );
-    
-	S32 width  = getWidth();
-    S32 height = getHeight();
-    
-	U8* dst_data = getData();
-	for (S32 j = 0; j < height; j++)
-	{
-        for (S32 i = 0; i < width; i++)
-        {
-            if (mVignetteMode == VIGNETTE_MODE_NONE)
-            {
-                dst_data[VRED]   = lut_red[dst_data[VRED]];
-                dst_data[VGREEN] = lut_green[dst_data[VGREEN]];
-                dst_data[VBLUE]  = lut_blue[dst_data[VBLUE]];
-            }
-            else
-            {
-                F32 alpha = getVignetteAlpha(i,j);
-                if (mVignetteMode == VIGNETTE_MODE_BLEND)
-                {
-                    // Blends with the source image on the edges
-                    F32 inv_alpha = 1.0 - alpha;
-                    dst_data[VRED]   = inv_alpha * dst_data[VRED]  + alpha * lut_red[dst_data[VRED]];
-                    dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * lut_green[dst_data[VGREEN]];
-                    dst_data[VBLUE]  = inv_alpha * dst_data[VBLUE]  + alpha * lut_blue[dst_data[VBLUE]];
-                }
-                else // VIGNETTE_MODE_FADE
-                {
-                    // Fade to black on the edges
-                    dst_data[VRED]   = alpha * lut_red[dst_data[VRED]];
-                    dst_data[VGREEN] = alpha * lut_green[dst_data[VGREEN]];
-                    dst_data[VBLUE]  = alpha * lut_blue[dst_data[VBLUE]];
-                }
-            }
-            dst_data += components;
-        }
-	}
-}
-
-void LLImageRaw::filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle)
-{
-	const S32 components = getComponents();
-	llassert( components >= 1 && components <= 4 );
-    
-	S32 width  = getWidth();
-    S32 height = getHeight();
-    
-    F32 sin = sinf(angle*DEG_TO_RAD);
-    F32 cos = cosf(angle*DEG_TO_RAD);
-    
-	U8* dst_data = getData();
-	for (S32 j = 0; j < height; j++)
-	{
-        for (S32 i = 0; i < width; i++)
-        {
-            F32 value = 0.0;
-            F32 d = 0.0;
-            switch (mode)
-            {
-                case SCREEN_MODE_2DSINE:
-                    value = (sinf(2*F_PI*i/wave_length)*sinf(2*F_PI*j/wave_length)+1.0)*255.0/2.0;
-                    break;
-                case SCREEN_MODE_LINE:
-                    d = sin*i - cos*j;
-                    value = (sinf(2*F_PI*d/wave_length)+1.0)*255.0/2.0;
-                    break;
-            }
-            U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0);
-            
-            if (mVignetteMode == VIGNETTE_MODE_NONE)
-            {
-                dst_data[VRED]   = dst_value;
-                dst_data[VGREEN] = dst_value;
-                dst_data[VBLUE]  = dst_value;
-            }
-            else
-            {
-                F32 alpha = getVignetteAlpha(i,j);
-                if (mVignetteMode == VIGNETTE_MODE_BLEND)
-                {
-                    // Blends with the source image on the edges
-                    F32 inv_alpha = 1.0 - alpha;
-                    dst_data[VRED]   = inv_alpha * dst_data[VRED]   + alpha * dst_value;
-                    dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * dst_value;
-                    dst_data[VBLUE]  = inv_alpha * dst_data[VBLUE]  + alpha * dst_value;
-                }
-                else // VIGNETTE_MODE_FADE
-                {
-                    // Fade to black on the edges
-                    dst_data[VRED]   = alpha * dst_value;
-                    dst_data[VGREEN] = alpha * dst_value;
-                    dst_data[VBLUE]  = alpha * dst_value;
-                }
-            }
-            dst_data += components;
-        }
-	}
-}
-
-void LLImageRaw::setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min)
-{
-    mVignetteMode = mode;
-    mVignetteType = type;
-    mVignetteGamma = gamma;
-    mVignetteMin = llclampf(min);
-    // We always center the vignette on the image and fits it in the image smallest dimension
-    mVignetteCenterX = getWidth()/2;
-    mVignetteCenterY = getHeight()/2;
-    mVignetteWidth = llmin(getWidth()/2,getHeight()/2);
-}
-
-F32 LLImageRaw::getVignetteAlpha(S32 i, S32 j)
-{
-    F32 alpha = 1.0;
-    if (mVignetteType == VIGNETTE_TYPE_CENTER)
-    {
-        // alpha is a modified gaussian value, with a center and fading in a circular pattern toward the edges
-        // The gamma parameter controls the intensity of the drop down from alpha 1.0 (center) to 0.0
-        F32 d_center_square = (i - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY);
-        alpha = powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f));
-    }
-    else if (mVignetteType == VIGNETTE_TYPE_LINES)
-    {
-        // alpha varies according to a squared sine function vertically.
-        // gamma is interpreted as the wavelength (in pixels) of the sine in that case.
-        alpha = (sinf(2*F_PI*j/mVignetteGamma) > 0.0 ? 1.0 : 0.0);
-    }
-    // We rescale alpha between min and 1.0 so to avoid complete fading if so desired.
-    return (mVignetteMin + alpha * (1.0 - mVignetteMin));
-}
-
-U32* LLImageRaw::getBrightnessHistogram()
-{
-    if (!mHistoBrightness)
-    {
-        computeHistograms();
-    }
-    return mHistoBrightness;
-}
-
-void LLImageRaw::computeHistograms()
-{
- 	const S32 components = getComponents();
-	llassert( components >= 1 && components <= 4 );
-    
-    // Allocate memory for the histograms
-    if (!mHistoRed)
-    {
-        mHistoRed = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
-    }
-    if (!mHistoGreen)
-    {
-        mHistoGreen = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
-    }
-    if (!mHistoBlue)
-    {
-        mHistoBlue = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
-    }
-    if (!mHistoBrightness)
-    {
-        mHistoBrightness = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
-    }
-    
-    // Initialize them
-    for (S32 i = 0; i < 256; i++)
-    {
-        mHistoRed[i] = 0;
-        mHistoGreen[i] = 0;
-        mHistoBlue[i] = 0;
-        mHistoBrightness[i] = 0;
-    }
-    
-    // Compute them
-	S32 pixels = getWidth() * getHeight();
-	U8* dst_data = getData();
-	for (S32 i = 0; i < pixels; i++)
-	{
-        mHistoRed[dst_data[VRED]]++;
-        mHistoGreen[dst_data[VGREEN]]++;
-        mHistoBlue[dst_data[VBLUE]]++;
-        // Note: this is a very simple shorthand for brightness but it's OK for our use
-        S32 brightness = ((S32)(dst_data[VRED]) + (S32)(dst_data[VGREEN]) + (S32)(dst_data[VBLUE])) / 3;
-        mHistoBrightness[brightness]++;
-        // next pixel...
-		dst_data += components;
-	}
-}
-
 void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step )
 {
 	const S32 components = getComponents();
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index a600f2e4a6..4b1da233e1 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -88,25 +88,6 @@ typedef enum e_image_codec
 	IMG_CODEC_EOF  = 8
 } EImageCodec;
 
-typedef enum e_vignette_mode
-{
-	VIGNETTE_MODE_NONE  = 0,
-	VIGNETTE_MODE_BLEND = 1,
-	VIGNETTE_MODE_FADE  = 2
-} EVignetteMode;
-
-typedef enum e_vignette_type
-{
-	VIGNETTE_TYPE_CENTER = 0,
-	VIGNETTE_TYPE_LINES  = 1
-} EVignetteType;
-
-typedef enum e_screen_mode
-{
-	SCREEN_MODE_2DSINE   = 0,
-	SCREEN_MODE_LINE     = 1
-} EScreenMode;
-
 //============================================================================
 // library initialization class
 
@@ -171,21 +152,6 @@ protected:
 	// special accessor to allow direct setting of mData and mDataSize by LLImageFormatted
 	void setDataAndSize(U8 *data, S32 size);
 	
-    // Histograms (if we ever happen to need them)
-    U32 *mHistoRed;
-    U32 *mHistoGreen;
-    U32 *mHistoBlue;
-    U32 *mHistoBrightness;
-    
-    // Vignette filtering
-    EVignetteMode mVignetteMode;
-    EVignetteType mVignetteType;
-    S32 mVignetteCenterX;
-    S32 mVignetteCenterY;
-    S32 mVignetteWidth;
-    F32 mVignetteGamma;
-    F32 mVignetteMin;
-    
 public:
 	static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels);
 	
@@ -291,30 +257,6 @@ public:
 
 	// Src and dst are same size.  Src has 4 components.  Dst has 3 components.
 	void compositeUnscaled4onto3( LLImageRaw* src );
-    
-    // Filter Operations : Transforms
-    void filterGrayScale();                         // Convert to grayscale
-    void filterSepia();                             // Convert to sepia
-    void filterSaturate(F32 saturation);            // < 1.0 desaturates, > 1.0 saturates
-    void filterRotate(F32 angle);                   // Rotates hue according to angle, angle in degrees
-    
-    // Filter Operations : Color Corrections
-    // When specified, the LLColor3 alpha parameter indicates the intensity of the effect for each color channel
-    // acting in effect as an alpha blending factor different for each channel. For instance (1.0,0.0,0.0) will apply
-    // the effect only to the Red channel. Intermediate values blends the effect with the source color.
-    void filterGamma(F32 gamma, const LLColor3& alpha);         // Apply gamma to each channel
-    void filterLinearize(F32 tail, const LLColor3& alpha);      // Use histogram to linearize constrast between min and max values minus tail
-    void filterEqualize(S32 nb_classes, const LLColor3& alpha); // Use histogram to equalize constrast between nb_classes throughout the image
-    void filterColorize(const LLColor3& color, const LLColor3& alpha);  // Colorize with color and alpha per channel
-    void filterContrast(F32 slope, const LLColor3& alpha);      // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast
-    void filterBrightness(S32 add, const LLColor3& alpha);      // Change brightness according to add: > 0 brighter, < 0 darker
-   
-    // Filter Primitives
-    void colorTransform(const LLMatrix3 &transform);
-    void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue);
-    void filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle);
-    void setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min);
-    U32* getBrightnessHistogram();
 
 protected:
 	// Create an image from a local file (generally used in tools)
@@ -327,9 +269,6 @@ protected:
 
 	void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ;
 
-    void computeHistograms();
-    F32 getVignetteAlpha(S32 i, S32 j);
-
 public:
 	static S32 sGlobalRawMemory;
 	static S32 sRawImageCount;
diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index e2d281e48d..ed97d9ae17 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -40,16 +40,28 @@
 //---------------------------------------------------------------------------
 
 LLImageFilter::LLImageFilter() :
-    mFilterData(LLSD::emptyArray())
+    mFilterData(LLSD::emptyArray()),
+    mImage(NULL),
+    mHistoRed(NULL),
+    mHistoGreen(NULL),
+    mHistoBlue(NULL),
+    mHistoBrightness(NULL),
+    mVignetteMode(VIGNETTE_MODE_NONE),
+    mVignetteGamma(1.0),
+    mVignetteMin(0.0)
 {
 }
 
 LLImageFilter::~LLImageFilter()
 {
+    mImage = NULL;
+    ll_aligned_free_16(mHistoRed);
+    ll_aligned_free_16(mHistoGreen);
+    ll_aligned_free_16(mHistoBlue);
+    ll_aligned_free_16(mHistoBrightness);
 }
 
 /*
- " -f, --filter <name> [<param>]\n"
  "        Apply the filter <name> to the input images using the optional <param> value. Admissible names:\n"
  "        - 'grayscale' converts to grayscale (no param).\n"
  "        - 'sepia' converts to sepia (no param).\n"
@@ -67,86 +79,10 @@ LLImageFilter::~LLImageFilter()
  "        - 'verticalscreen' applies a vertical screening to the red channel and output to black and white.\n"
  "        - 'slantedscreen' applies a 45 degrees slanted screening to the red channel and output to black and white.\n"
  "        - Any other value will be interpreted as a file name describing a sequence of filters and parameters to be applied to the input images.\n"
- " -v, --vignette <name> [<feather> <min>]\n"
+
  "        Apply a circular central vignette <name> to the filter using the optional <feather> and <min> values. Admissible names:\n"
  "        - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n"
  "        - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n"
-
- // Set the vignette if any
- if (vignette_name == "blend")
- {
- raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2));
- }
- else if (vignette_name == "fade")
- {
- raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2));
- }
- 
- // Apply filter if any
- if (filter_name == "sepia")
- {
- raw_image->filterSepia();
- }
- else if (filter_name == "grayscale")
- {
- raw_image->filterGrayScale();
- }
- else if (filter_name == "saturate")
- {
- raw_image->filterSaturate((float)(filter_param));
- }
- else if (filter_name == "rotate")
- {
- raw_image->filterRotate((float)(filter_param));
- }
- else if (filter_name == "gamma")
- {
- raw_image->filterGamma((float)(filter_param),LLColor3::white);
- }
- else if (filter_name == "colorize")
- {
- // For testing, we just colorize in the red channel, modulate by the alpha passed as a parameter
- LLColor3 color(1.0,0.0,0.0);
- LLColor3 alpha((F32)(filter_param),0.0,0.0);
- raw_image->filterColorize(color,alpha);
- }
- else if (filter_name == "contrast")
- {
- raw_image->filterContrast((float)(filter_param),LLColor3::white);
- }
- else if (filter_name == "brighten")
- {
- raw_image->filterBrightness((S32)(filter_param),LLColor3::white);
- }
- else if (filter_name == "darken")
- {
- raw_image->filterBrightness((S32)(-filter_param),LLColor3::white);
- }
- else if (filter_name == "linearize")
- {
- raw_image->filterLinearize((float)(filter_param),LLColor3::white);
- }
- else if (filter_name == "posterize")
- {
- raw_image->filterEqualize((S32)(filter_param),LLColor3::white);
- }
- else if (filter_name == "newsscreen")
- {
- raw_image->filterScreen(SCREEN_MODE_2DSINE,(S32)(filter_param),0.0);
- }
- else if (filter_name == "horizontalscreen")
- {
- raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),0.0);
- }
- else if (filter_name == "verticalscreen")
- {
- raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),90.0);
- }
- else if (filter_name == "slantedscreen")
- {
- raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),45.0);
- }
- 
  */
 
 // Load filter from file
@@ -171,6 +107,8 @@ void LLImageFilter::loadFromFile(const std::string& file_path)
 // Apply the filter data to the image passed as parameter
 void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
 {
+    mImage = raw_image;
+    
 	//std::cout << "Filter : size = " << mFilterData.size() << std::endl;
 	for (S32 i = 0; i < mFilterData.size(); ++i)
 	{
@@ -186,67 +124,67 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
         // Execute the filter described on this line
         if (filter_name == "blend")
         {
-            raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()));
+            setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()));
         }
         else if (filter_name == "fade")
         {
-            raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()));
+            setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()));
         }
         else if (filter_name == "lines")
         {
-            raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()));
+            setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()));
         }
         else if (filter_name == "sepia")
         {
-            raw_image->filterSepia();
+            filterSepia();
         }
         else if (filter_name == "grayscale")
         {
-            raw_image->filterGrayScale();
+            filterGrayScale();
         }
         else if (filter_name == "saturate")
         {
-            raw_image->filterSaturate((float)(mFilterData[i][1].asReal()));
+            filterSaturate((float)(mFilterData[i][1].asReal()));
         }
         else if (filter_name == "rotate")
         {
-            raw_image->filterRotate((float)(mFilterData[i][1].asReal()));
+            filterRotate((float)(mFilterData[i][1].asReal()));
         }
         else if (filter_name == "gamma")
         {
             LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
-            raw_image->filterGamma((float)(mFilterData[i][1].asReal()),color);
+            filterGamma((float)(mFilterData[i][1].asReal()),color);
         }
         else if (filter_name == "colorize")
         {
             LLColor3 color((float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()));
             LLColor3 alpha((F32)(mFilterData[i][4].asReal()),(float)(mFilterData[i][5].asReal()),(float)(mFilterData[i][6].asReal()));
-            raw_image->filterColorize(color,alpha);
+            filterColorize(color,alpha);
         }
         else if (filter_name == "contrast")
         {
             LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
-            raw_image->filterContrast((float)(mFilterData[i][1].asReal()),color);
+            filterContrast((float)(mFilterData[i][1].asReal()),color);
         }
         else if (filter_name == "brighten")
         {
             LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
-            raw_image->filterBrightness((S32)(mFilterData[i][1].asReal()),color);
+            filterBrightness((S32)(mFilterData[i][1].asReal()),color);
         }
         else if (filter_name == "darken")
         {
             LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
-            raw_image->filterBrightness((S32)(-mFilterData[i][1].asReal()),color);
+            filterBrightness((S32)(-mFilterData[i][1].asReal()),color);
         }
         else if (filter_name == "linearize")
         {
             LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
-            raw_image->filterLinearize((float)(mFilterData[i][1].asReal()),color);
+            filterLinearize((float)(mFilterData[i][1].asReal()),color);
         }
         else if (filter_name == "posterize")
         {
             LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
-            raw_image->filterEqualize((S32)(mFilterData[i][1].asReal()),color);
+            filterEqualize((S32)(mFilterData[i][1].asReal()),color);
         }
         else if (filter_name == "screen")
         {
@@ -260,10 +198,525 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
             {
                 mode = SCREEN_MODE_LINE;
             }
-            raw_image->filterScreen(mode,(S32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal()));
+            filterScreen(mode,(S32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal()));
         }
     }
 }
 
+// Filter Primitives
+void LLImageFilter::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue)
+{
+	const S32 components = mImage->getComponents();
+	llassert( components >= 1 && components <= 4 );
+    
+	S32 width  = mImage->getWidth();
+    S32 height = mImage->getHeight();
+    
+	U8* dst_data = mImage->getData();
+	for (S32 j = 0; j < height; j++)
+	{
+        for (S32 i = 0; i < width; i++)
+        {
+            if (mVignetteMode == VIGNETTE_MODE_NONE)
+            {
+                dst_data[VRED]   = lut_red[dst_data[VRED]];
+                dst_data[VGREEN] = lut_green[dst_data[VGREEN]];
+                dst_data[VBLUE]  = lut_blue[dst_data[VBLUE]];
+            }
+            else
+            {
+                F32 alpha = getVignetteAlpha(i,j);
+                if (mVignetteMode == VIGNETTE_MODE_BLEND)
+                {
+                    // Blends with the source image on the edges
+                    F32 inv_alpha = 1.0 - alpha;
+                    dst_data[VRED]   = inv_alpha * dst_data[VRED]  + alpha * lut_red[dst_data[VRED]];
+                    dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * lut_green[dst_data[VGREEN]];
+                    dst_data[VBLUE]  = inv_alpha * dst_data[VBLUE]  + alpha * lut_blue[dst_data[VBLUE]];
+                }
+                else // VIGNETTE_MODE_FADE
+                {
+                    // Fade to black on the edges
+                    dst_data[VRED]   = alpha * lut_red[dst_data[VRED]];
+                    dst_data[VGREEN] = alpha * lut_green[dst_data[VGREEN]];
+                    dst_data[VBLUE]  = alpha * lut_blue[dst_data[VBLUE]];
+                }
+            }
+            dst_data += components;
+        }
+	}
+}
+
+void LLImageFilter::colorTransform(const LLMatrix3 &transform)
+{
+	const S32 components = mImage->getComponents();
+	llassert( components >= 1 && components <= 4 );
+    
+	S32 width  = mImage->getWidth();
+    S32 height = mImage->getHeight();
+    
+	U8* dst_data = mImage->getData();
+	for (S32 j = 0; j < height; j++)
+	{
+        for (S32 i = 0; i < width; i++)
+        {
+            LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE]));
+            LLVector3 dst = src * transform;
+            dst.clamp(0.0f,255.0f);
+            if (mVignetteMode == VIGNETTE_MODE_NONE)
+            {
+                dst_data[VRED]   = dst.mV[VRED];
+                dst_data[VGREEN] = dst.mV[VGREEN];
+                dst_data[VBLUE]  = dst.mV[VBLUE];
+            }
+            else
+            {
+                F32 alpha = getVignetteAlpha(i,j);
+                if (mVignetteMode == VIGNETTE_MODE_BLEND)
+                {
+                    // Blends with the source image on the edges
+                    F32 inv_alpha = 1.0 - alpha;
+                    dst_data[VRED]   = inv_alpha * src.mV[VRED]   + alpha * dst.mV[VRED];
+                    dst_data[VGREEN] = inv_alpha * src.mV[VGREEN] + alpha * dst.mV[VGREEN];
+                    dst_data[VBLUE]  = inv_alpha * src.mV[VBLUE]  + alpha * dst.mV[VBLUE];
+                }
+                else // VIGNETTE_MODE_FADE
+                {
+                    // Fade to black on the edges
+                    dst_data[VRED]   = alpha * dst.mV[VRED];
+                    dst_data[VGREEN] = alpha * dst.mV[VGREEN];
+                    dst_data[VBLUE]  = alpha * dst.mV[VBLUE];
+                }
+            }
+            dst_data += components;
+        }
+	}
+}
+
+void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle)
+{
+	const S32 components = mImage->getComponents();
+	llassert( components >= 1 && components <= 4 );
+    
+	S32 width  = mImage->getWidth();
+    S32 height = mImage->getHeight();
+    
+    F32 sin = sinf(angle*DEG_TO_RAD);
+    F32 cos = cosf(angle*DEG_TO_RAD);
+    
+	U8* dst_data = mImage->getData();
+	for (S32 j = 0; j < height; j++)
+	{
+        for (S32 i = 0; i < width; i++)
+        {
+            F32 value = 0.0;
+            F32 d = 0.0;
+            switch (mode)
+            {
+                case SCREEN_MODE_2DSINE:
+                    value = (sinf(2*F_PI*i/wave_length)*sinf(2*F_PI*j/wave_length)+1.0)*255.0/2.0;
+                    break;
+                case SCREEN_MODE_LINE:
+                    d = sin*i - cos*j;
+                    value = (sinf(2*F_PI*d/wave_length)+1.0)*255.0/2.0;
+                    break;
+            }
+            U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0);
+            
+            if (mVignetteMode == VIGNETTE_MODE_NONE)
+            {
+                dst_data[VRED]   = dst_value;
+                dst_data[VGREEN] = dst_value;
+                dst_data[VBLUE]  = dst_value;
+            }
+            else
+            {
+                F32 alpha = getVignetteAlpha(i,j);
+                if (mVignetteMode == VIGNETTE_MODE_BLEND)
+                {
+                    // Blends with the source image on the edges
+                    F32 inv_alpha = 1.0 - alpha;
+                    dst_data[VRED]   = inv_alpha * dst_data[VRED]   + alpha * dst_value;
+                    dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * dst_value;
+                    dst_data[VBLUE]  = inv_alpha * dst_data[VBLUE]  + alpha * dst_value;
+                }
+                else // VIGNETTE_MODE_FADE
+                {
+                    // Fade to black on the edges
+                    dst_data[VRED]   = alpha * dst_value;
+                    dst_data[VGREEN] = alpha * dst_value;
+                    dst_data[VBLUE]  = alpha * dst_value;
+                }
+            }
+            dst_data += components;
+        }
+	}
+}
+
+// Procedural Stencils
+void LLImageFilter::setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min)
+{
+    mVignetteMode = mode;
+    mVignetteType = type;
+    mVignetteGamma = gamma;
+    mVignetteMin = llclampf(min);
+    // We always center the vignette on the image and fits it in the image smallest dimension
+    mVignetteCenterX = mImage->getWidth()/2;
+    mVignetteCenterY = mImage->getHeight()/2;
+    mVignetteWidth = llmin(mImage->getWidth()/2,mImage->getHeight()/2);
+}
+
+F32 LLImageFilter::getVignetteAlpha(S32 i, S32 j)
+{
+    F32 alpha = 1.0;
+    if (mVignetteType == VIGNETTE_TYPE_CENTER)
+    {
+        // alpha is a modified gaussian value, with a center and fading in a circular pattern toward the edges
+        // The gamma parameter controls the intensity of the drop down from alpha 1.0 (center) to 0.0
+        F32 d_center_square = (i - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY);
+        alpha = powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f));
+    }
+    else if (mVignetteType == VIGNETTE_TYPE_LINES)
+    {
+        // alpha varies according to a squared sine function vertically.
+        // gamma is interpreted as the wavelength (in pixels) of the sine in that case.
+        alpha = (sinf(2*F_PI*j/mVignetteGamma) > 0.0 ? 1.0 : 0.0);
+    }
+    // We rescale alpha between min and 1.0 so to avoid complete fading if so desired.
+    return (mVignetteMin + alpha * (1.0 - mVignetteMin));
+}
+
+// Histograms
+U32* LLImageFilter::getBrightnessHistogram()
+{
+    if (!mHistoBrightness)
+    {
+        computeHistograms();
+    }
+    return mHistoBrightness;
+}
+
+void LLImageFilter::computeHistograms()
+{
+ 	const S32 components = mImage->getComponents();
+	llassert( components >= 1 && components <= 4 );
+    
+    // Allocate memory for the histograms
+    if (!mHistoRed)
+    {
+        mHistoRed = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
+    }
+    if (!mHistoGreen)
+    {
+        mHistoGreen = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
+    }
+    if (!mHistoBlue)
+    {
+        mHistoBlue = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
+    }
+    if (!mHistoBrightness)
+    {
+        mHistoBrightness = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
+    }
+    
+    // Initialize them
+    for (S32 i = 0; i < 256; i++)
+    {
+        mHistoRed[i] = 0;
+        mHistoGreen[i] = 0;
+        mHistoBlue[i] = 0;
+        mHistoBrightness[i] = 0;
+    }
+    
+    // Compute them
+	S32 pixels = mImage->getWidth() * mImage->getHeight();
+	U8* dst_data = mImage->getData();
+	for (S32 i = 0; i < pixels; i++)
+	{
+        mHistoRed[dst_data[VRED]]++;
+        mHistoGreen[dst_data[VGREEN]]++;
+        mHistoBlue[dst_data[VBLUE]]++;
+        // Note: this is a very simple shorthand for brightness but it's OK for our use
+        S32 brightness = ((S32)(dst_data[VRED]) + (S32)(dst_data[VGREEN]) + (S32)(dst_data[VBLUE])) / 3;
+        mHistoBrightness[brightness]++;
+        // next pixel...
+		dst_data += components;
+	}
+}
+
+// Secondary Filters
+void LLImageFilter::filterGrayScale()
+{
+    LLMatrix3 gray_scale;
+    LLVector3 luminosity(0.2125, 0.7154, 0.0721);
+    gray_scale.setRows(luminosity, luminosity, luminosity);
+    gray_scale.transpose();
+    colorTransform(gray_scale);
+}
+
+void LLImageFilter::filterSepia()
+{
+    LLMatrix3 sepia;
+    sepia.setRows(LLVector3(0.3588, 0.7044, 0.1368),
+                  LLVector3(0.2990, 0.5870, 0.1140),
+                  LLVector3(0.2392, 0.4696, 0.0912));
+    sepia.transpose();
+    colorTransform(sepia);
+}
+
+void LLImageFilter::filterSaturate(F32 saturation)
+{
+    // Matrix to Lij
+    LLMatrix3 r_a;
+    LLMatrix3 r_b;
+    
+    // 45 degre rotation around z
+    r_a.setRows(LLVector3( OO_SQRT2,  OO_SQRT2, 0.0),
+                LLVector3(-OO_SQRT2,  OO_SQRT2, 0.0),
+                LLVector3( 0.0,       0.0,      1.0));
+    // 54.73 degre rotation around y
+    float oo_sqrt3 = 1.0f / F_SQRT3;
+    float sin_54 = F_SQRT2 * oo_sqrt3;
+    r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54),
+                LLVector3(0.0,      1.0,  0.0),
+                LLVector3(sin_54,   0.0,  oo_sqrt3));
+    
+    // Coordinate conversion
+    LLMatrix3 Lij = r_b * r_a;
+    LLMatrix3 Lij_inv = Lij;
+    Lij_inv.transpose();
+    
+    // Local saturation transform
+    LLMatrix3 s;
+    s.setRows(LLVector3(saturation, 0.0,  0.0),
+              LLVector3(0.0,  saturation, 0.0),
+              LLVector3(0.0,        0.0,  1.0));
+    
+    // Global saturation transform
+    LLMatrix3 transfo = Lij_inv * s * Lij;
+    colorTransform(transfo);
+}
+
+void LLImageFilter::filterRotate(F32 angle)
+{
+    // Matrix to Lij
+    LLMatrix3 r_a;
+    LLMatrix3 r_b;
+    
+    // 45 degre rotation around z
+    r_a.setRows(LLVector3( OO_SQRT2,  OO_SQRT2, 0.0),
+                LLVector3(-OO_SQRT2,  OO_SQRT2, 0.0),
+                LLVector3( 0.0,       0.0,      1.0));
+    // 54.73 degre rotation around y
+    float oo_sqrt3 = 1.0f / F_SQRT3;
+    float sin_54 = F_SQRT2 * oo_sqrt3;
+    r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54),
+                LLVector3(0.0,      1.0,  0.0),
+                LLVector3(sin_54,   0.0,  oo_sqrt3));
+    
+    // Coordinate conversion
+    LLMatrix3 Lij = r_b * r_a;
+    LLMatrix3 Lij_inv = Lij;
+    Lij_inv.transpose();
+    
+    // Local color rotation transform
+    LLMatrix3 r;
+    angle *= DEG_TO_RAD;
+    r.setRows(LLVector3( cosf(angle), sinf(angle), 0.0),
+              LLVector3(-sinf(angle), cosf(angle), 0.0),
+              LLVector3( 0.0,         0.0,         1.0));
+    
+    // Global color rotation transform
+    LLMatrix3 transfo = Lij_inv * r * Lij;
+    colorTransform(transfo);
+}
+
+void LLImageFilter::filterGamma(F32 gamma, const LLColor3& alpha)
+{
+    U8 gamma_red_lut[256];
+    U8 gamma_green_lut[256];
+    U8 gamma_blue_lut[256];
+    
+    for (S32 i = 0; i < 256; i++)
+    {
+        F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,gamma)));
+        // Blend in with alpha values
+        gamma_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * 255.0 * gamma_i);
+        gamma_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * 255.0 * gamma_i);
+        gamma_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * 255.0 * gamma_i);
+    }
+    
+    colorCorrect(gamma_red_lut,gamma_green_lut,gamma_blue_lut);
+}
+
+void LLImageFilter::filterLinearize(F32 tail, const LLColor3& alpha)
+{
+    // Get the histogram
+    U32* histo = getBrightnessHistogram();
+    
+    // Compute cumulated histogram
+    U32 cumulated_histo[256];
+    cumulated_histo[0] = histo[0];
+    for (S32 i = 1; i < 256; i++)
+    {
+        cumulated_histo[i] = cumulated_histo[i-1] + histo[i];
+    }
+    
+    // Compute min and max counts minus tail
+    tail = llclampf(tail);
+    S32 total = cumulated_histo[255];
+    S32 min_c = (S32)((F32)(total) * tail);
+    S32 max_c = (S32)((F32)(total) * (1.0 - tail));
+    
+    // Find min and max values
+    S32 min_v = 0;
+    while (cumulated_histo[min_v] < min_c)
+    {
+        min_v++;
+    }
+    S32 max_v = 255;
+    while (cumulated_histo[max_v] > max_c)
+    {
+        max_v--;
+    }
+    
+    // Compute linear lookup table
+    U8 linear_red_lut[256];
+    U8 linear_green_lut[256];
+    U8 linear_blue_lut[256];
+    if (max_v == min_v)
+    {
+        // Degenerated binary split case
+        for (S32 i = 0; i < 256; i++)
+        {
+            U8 value_i = (i < min_v ? 0 : 255);
+            // Blend in with alpha values
+            linear_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
+            linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
+            linear_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
+        }
+    }
+    else
+    {
+        // Linearize between min and max
+        F32 slope = 255.0 / (F32)(max_v - min_v);
+        F32 translate = -min_v * slope;
+        for (S32 i = 0; i < 256; i++)
+        {
+            U8 value_i = (U8)(llclampb((S32)(slope*i + translate)));
+            // Blend in with alpha values
+            linear_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
+            linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
+            linear_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
+        }
+    }
+    
+    // Apply lookup table
+    colorCorrect(linear_red_lut,linear_green_lut,linear_blue_lut);
+}
+
+void LLImageFilter::filterEqualize(S32 nb_classes, const LLColor3& alpha)
+{
+    // Regularize the parameter: must be between 2 and 255
+    nb_classes = llmax(nb_classes,2);
+    nb_classes = llclampb(nb_classes);
+    
+    // Get the histogram
+    U32* histo = getBrightnessHistogram();
+    
+    // Compute cumulated histogram
+    U32 cumulated_histo[256];
+    cumulated_histo[0] = histo[0];
+    for (S32 i = 1; i < 256; i++)
+    {
+        cumulated_histo[i] = cumulated_histo[i-1] + histo[i];
+    }
+    
+    // Compute deltas
+    S32 total = cumulated_histo[255];
+    S32 delta_count = total / nb_classes;
+    S32 current_count = delta_count;
+    S32 delta_value = 256 / (nb_classes - 1);
+    S32 current_value = 0;
+    
+    // Compute equalized lookup table
+    U8 equalize_red_lut[256];
+    U8 equalize_green_lut[256];
+    U8 equalize_blue_lut[256];
+    for (S32 i = 0; i < 256; i++)
+    {
+        // Blend in current_value with alpha values
+        equalize_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * current_value);
+        equalize_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * current_value);
+        equalize_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * current_value);
+        if (cumulated_histo[i] >= current_count)
+        {
+            current_count += delta_count;
+            current_value += delta_value;
+            current_value = llclampb(current_value);
+        }
+    }
+    
+    // Apply lookup table
+    colorCorrect(equalize_red_lut,equalize_green_lut,equalize_blue_lut);
+}
+
+void LLImageFilter::filterColorize(const LLColor3& color, const LLColor3& alpha)
+{
+    U8 red_lut[256];
+    U8 green_lut[256];
+    U8 blue_lut[256];
+    
+    F32 red_composite   =  255.0 * alpha.mV[0] * color.mV[0];
+    F32 green_composite =  255.0 * alpha.mV[1] * color.mV[1];
+    F32 blue_composite  =  255.0 * alpha.mV[2] * color.mV[2];
+    
+    for (S32 i = 0; i < 256; i++)
+    {
+        red_lut[i]   = (U8)(llclampb((S32)((1.0 - alpha.mV[0]) * (F32)(i) + red_composite)));
+        green_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[1]) * (F32)(i) + green_composite)));
+        blue_lut[i]  = (U8)(llclampb((S32)((1.0 - alpha.mV[2]) * (F32)(i) + blue_composite)));
+    }
+    
+    colorCorrect(red_lut,green_lut,blue_lut);
+}
+
+void LLImageFilter::filterContrast(F32 slope, const LLColor3& alpha)
+{
+    U8 contrast_red_lut[256];
+    U8 contrast_green_lut[256];
+    U8 contrast_blue_lut[256];
+    
+    F32 translate = 128.0 * (1.0 - slope);
+    
+    for (S32 i = 0; i < 256; i++)
+    {
+        U8 value_i = (U8)(llclampb((S32)(slope*i + translate)));
+        // Blend in with alpha values
+        contrast_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
+        contrast_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
+        contrast_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
+    }
+    
+    colorCorrect(contrast_red_lut,contrast_green_lut,contrast_blue_lut);
+}
+
+void LLImageFilter::filterBrightness(S32 add, const LLColor3& alpha)
+{
+    U8 brightness_red_lut[256];
+    U8 brightness_green_lut[256];
+    U8 brightness_blue_lut[256];
+    
+    for (S32 i = 0; i < 256; i++)
+    {
+        U8 value_i = (U8)(llclampb((S32)((S32)(i) + add)));
+        // Blend in with alpha values
+        brightness_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
+        brightness_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
+        brightness_blue_lut[i]  = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
+    }
+    
+    colorCorrect(brightness_red_lut,brightness_green_lut,brightness_blue_lut);
+}
 
 //============================================================================
diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h
index 5598fa69f5..c67789ede0 100755
--- a/indra/llimage/llimagefilter.h
+++ b/indra/llimage/llimagefilter.h
@@ -29,7 +29,6 @@
 
 #include "llimage.h"
 
-/*
 class LLImageRaw;
 class LLColor4U;
 class LLColor3;
@@ -53,7 +52,7 @@ typedef enum e_screen_mode
 	SCREEN_MODE_2DSINE   = 0,
 	SCREEN_MODE_LINE     = 1
 } EScreenMode;
-*/
+
 //============================================================================
 // Image Filter 
 
@@ -65,8 +64,55 @@ public:
     
     void loadFromFile(const std::string& file_path);
     void executeFilter(LLPointer<LLImageRaw> raw_image);
+    
 private:
+    // Filter Operations : Transforms
+    void filterGrayScale();                         // Convert to grayscale
+    void filterSepia();                             // Convert to sepia
+    void filterSaturate(F32 saturation);            // < 1.0 desaturates, > 1.0 saturates
+    void filterRotate(F32 angle);                   // Rotates hue according to angle, angle in degrees
+    
+    // Filter Operations : Color Corrections
+    // When specified, the LLColor3 alpha parameter indicates the intensity of the effect for each color channel
+    // acting in effect as an alpha blending factor different for each channel. For instance (1.0,0.0,0.0) will apply
+    // the effect only to the Red channel. Intermediate values blends the effect with the source color.
+    void filterGamma(F32 gamma, const LLColor3& alpha);         // Apply gamma to each channel
+    void filterLinearize(F32 tail, const LLColor3& alpha);      // Use histogram to linearize constrast between min and max values minus tail
+    void filterEqualize(S32 nb_classes, const LLColor3& alpha); // Use histogram to equalize constrast between nb_classes throughout the image
+    void filterColorize(const LLColor3& color, const LLColor3& alpha);  // Colorize with color and alpha per channel
+    void filterContrast(F32 slope, const LLColor3& alpha);      // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast
+    void filterBrightness(S32 add, const LLColor3& alpha);      // Change brightness according to add: > 0 brighter, < 0 darker
+    
+    // Filter Primitives
+    void colorTransform(const LLMatrix3 &transform);
+    void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue);
+    void filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle);
+
+    // Procedural Stencils
+    void setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min);
+    F32 getVignetteAlpha(S32 i, S32 j);
+
+    // Histograms
+    U32* getBrightnessHistogram();
+    void computeHistograms();
+
     LLSD mFilterData;
+    LLPointer<LLImageRaw> mImage;
+
+    // Histograms (if we ever happen to need them)
+    U32 *mHistoRed;
+    U32 *mHistoGreen;
+    U32 *mHistoBlue;
+    U32 *mHistoBrightness;
+    
+    // Vignette filtering
+    EVignetteMode mVignetteMode;
+    EVignetteType mVignetteType;
+    S32 mVignetteCenterX;
+    S32 mVignetteCenterY;
+    S32 mVignetteWidth;
+    F32 mVignetteGamma;
+    F32 mVignetteMin;
 };
 
 
-- 
cgit v1.2.3


From f1229912280fe67b272f5c1ba424524d738ed867 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 15 Jan 2014 09:24:06 -0800
Subject: ACME-1236 : Add comments to LLImageFilter

---
 indra/llimage/llimagefilter.cpp | 46 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index ed97d9ae17..5c969001b7 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -62,6 +62,34 @@ LLImageFilter::~LLImageFilter()
 }
 
 /*
+ *TODO 
+ * Rename vignette to stencil
+ * Separate shape from mode
+ * Add shapes : uniform and gradients
+ * Add modes
+ * Add stencil (min,max) range
+ * Suppress alpha from colorcorrect and use uniform alpha instead
+ * Refactor stencil composition in the filter primitives
+ 
+ <array>
+ <string>stencil</string>
+ <string>shape</string>
+ <string>blend_mode</string>
+ <real>min</real>
+ <real>max</real>
+ <real>param1</real>
+ <real>param2</real>
+ <real>param3</real>
+ <real>param4</real>
+ </array>
+ 
+ vignette : center_x, center_y, width, feather
+ sine : wavelength, angle
+ flat
+ gradient : start_x, start_y, end_x, end_y
+
+ * Document all the admissible names in the wiki
+ 
  "        Apply the filter <name> to the input images using the optional <param> value. Admissible names:\n"
  "        - 'grayscale' converts to grayscale (no param).\n"
  "        - 'sepia' converts to sepia (no param).\n"
@@ -85,7 +113,10 @@ LLImageFilter::~LLImageFilter()
  "        - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n"
  */
 
+//============================================================================
 // Load filter from file
+//============================================================================
+
 void LLImageFilter::loadFromFile(const std::string& file_path)
 {
 	//std::cout << "Loading filter settings from : " << file_path << std::endl;
@@ -104,7 +135,10 @@ void LLImageFilter::loadFromFile(const std::string& file_path)
 	}
 }
 
+//============================================================================
 // Apply the filter data to the image passed as parameter
+//============================================================================
+
 void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
 {
     mImage = raw_image;
@@ -203,7 +237,10 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
     }
 }
 
+//============================================================================
 // Filter Primitives
+//============================================================================
+
 void LLImageFilter::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue)
 {
 	const S32 components = mImage->getComponents();
@@ -353,7 +390,10 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const
 	}
 }
 
+//============================================================================
 // Procedural Stencils
+//============================================================================
+
 void LLImageFilter::setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min)
 {
     mVignetteMode = mode;
@@ -386,7 +426,10 @@ F32 LLImageFilter::getVignetteAlpha(S32 i, S32 j)
     return (mVignetteMin + alpha * (1.0 - mVignetteMin));
 }
 
+//============================================================================
 // Histograms
+//============================================================================
+
 U32* LLImageFilter::getBrightnessHistogram()
 {
     if (!mHistoBrightness)
@@ -444,7 +487,10 @@ void LLImageFilter::computeHistograms()
 	}
 }
 
+//============================================================================
 // Secondary Filters
+//============================================================================
+
 void LLImageFilter::filterGrayScale()
 {
     LLMatrix3 gray_scale;
-- 
cgit v1.2.3


From 349e5565348ea68d0e74af605876ac373b6805c3 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 15 Jan 2014 09:42:34 -0800
Subject: ACME-1245 : Tweak a bit the Video.xml filter

---
 indra/newview/app_settings/filters/Video.xml | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/indra/newview/app_settings/filters/Video.xml b/indra/newview/app_settings/filters/Video.xml
index 8b10687ef5..144f340f12 100755
--- a/indra/newview/app_settings/filters/Video.xml
+++ b/indra/newview/app_settings/filters/Video.xml
@@ -2,7 +2,14 @@
     <array>
         <array>
             <string>linearize</string>
-            <real>0.01</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>darken</string>
+            <real>15.0</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
@@ -14,7 +21,7 @@
         </array>
         <array>
             <string>brighten</string>
-            <real>100.0</real>
+            <real>30.0</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
-- 
cgit v1.2.3


From 4b2e69d8e054134bea7216639effef90b51c3aae Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 15 Jan 2014 10:27:49 -0800
Subject: ACME-1236 : Clean up llimage after refactoring so there's no
 difference with viewer-release

---
 indra/llimage/llimage.cpp | 7 ++-----
 indra/llimage/llimage.h   | 2 --
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 7981ca7364..c8a05e1fae 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -29,10 +29,7 @@
 #include "llimage.h"
 
 #include "llmath.h"
-#include "v3color.h"
 #include "v4coloru.h"
-#include "m3math.h"
-#include "v3math.h"
 
 #include "llimagebmp.h"
 #include "llimagetga.h"
@@ -108,8 +105,8 @@ LLImageBase::~LLImageBase()
 	deleteData(); // virtual
 }
 
-//static
-void LLImageBase::createPrivatePool()
+//static 
+void LLImageBase::createPrivatePool() 
 {
 	if(!sPrivatePoolp)
 	{
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 4b1da233e1..2277afc585 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -71,8 +71,6 @@ const S32 HTTP_PACKET_SIZE = 1496;
 class LLImageFormatted;
 class LLImageRaw;
 class LLColor4U;
-class LLColor3;
-class LLMatrix3;
 class LLPrivateMemoryPool;
 
 typedef enum e_image_codec
-- 
cgit v1.2.3


From e0412a7d987e046c48f80992c3c7b2bdb3373201 Mon Sep 17 00:00:00 2001
From: merov <none@none>
Date: Thu, 16 Jan 2014 22:46:37 +0000
Subject: ACME-1237 : Rename filters so that it doesn't trip Windows NSIS
 script installer (ridiculous...)

---
 indra/newview/app_settings/filters/1970s color.xml | 41 ----------------------
 .../newview/app_settings/filters/Black & white.xml | 21 -----------
 .../newview/app_settings/filters/BlackAndWhite.xml | 21 +++++++++++
 indra/newview/app_settings/filters/Colors1970.xml  | 41 ++++++++++++++++++++++
 indra/newview/app_settings/filters/Jules Verne.xml | 25 -------------
 indra/newview/app_settings/filters/JulesVerne.xml  | 25 +++++++++++++
 6 files changed, 87 insertions(+), 87 deletions(-)
 delete mode 100644 indra/newview/app_settings/filters/1970s color.xml
 delete mode 100644 indra/newview/app_settings/filters/Black & white.xml
 create mode 100644 indra/newview/app_settings/filters/BlackAndWhite.xml
 create mode 100644 indra/newview/app_settings/filters/Colors1970.xml
 delete mode 100644 indra/newview/app_settings/filters/Jules Verne.xml
 create mode 100644 indra/newview/app_settings/filters/JulesVerne.xml

diff --git a/indra/newview/app_settings/filters/1970s color.xml b/indra/newview/app_settings/filters/1970s color.xml
deleted file mode 100644
index 0dab2489a0..0000000000
--- a/indra/newview/app_settings/filters/1970s color.xml	
+++ /dev/null
@@ -1,41 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>contrast</string>
-            <real>0.8</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>colorize</string>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>0.5</real>
-            <real>0.0</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>blend</string>
-            <real>10.0</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>colorize</string>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>0.1</real>
-            <real>0.1</real>
-            <real>0.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/Black & white.xml b/indra/newview/app_settings/filters/Black & white.xml
deleted file mode 100644
index 101ed8233a..0000000000
--- a/indra/newview/app_settings/filters/Black & white.xml	
+++ /dev/null
@@ -1,21 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.01</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>contrast</string>
-            <real>0.8</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>grayscale</string>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/BlackAndWhite.xml b/indra/newview/app_settings/filters/BlackAndWhite.xml
new file mode 100644
index 0000000000..101ed8233a
--- /dev/null
+++ b/indra/newview/app_settings/filters/BlackAndWhite.xml
@@ -0,0 +1,21 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.01</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Colors1970.xml b/indra/newview/app_settings/filters/Colors1970.xml
new file mode 100644
index 0000000000..0dab2489a0
--- /dev/null
+++ b/indra/newview/app_settings/filters/Colors1970.xml
@@ -0,0 +1,41 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.5</real>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>blend</string>
+            <real>10.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.1</real>
+            <real>0.1</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Jules Verne.xml b/indra/newview/app_settings/filters/Jules Verne.xml
deleted file mode 100644
index ddff4d1977..0000000000
--- a/indra/newview/app_settings/filters/Jules Verne.xml	
+++ /dev/null
@@ -1,25 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>grayscale</string>
-        </array>
-        <array>
-            <string>blend</string>
-            <real>0.0</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>screen</string>
-            <string>line</string>
-            <real>5.0</real>
-            <real>0.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/JulesVerne.xml b/indra/newview/app_settings/filters/JulesVerne.xml
new file mode 100644
index 0000000000..ddff4d1977
--- /dev/null
+++ b/indra/newview/app_settings/filters/JulesVerne.xml
@@ -0,0 +1,25 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+        <array>
+            <string>blend</string>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>screen</string>
+            <string>line</string>
+            <real>5.0</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
-- 
cgit v1.2.3


From 91f401fa2de8c78da7c83561501a1be993588867 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Thu, 16 Jan 2014 17:52:14 -0800
Subject: ACME-1237 : Use translation service for filter names so they can be
 localized and as also look proper in English. General filter manager cleanup

---
 indra/newview/llimagefiltersmanager.cpp        | 58 ++++++++++++++++----------
 indra/newview/llimagefiltersmanager.h          | 31 +++-----------
 indra/newview/llsnapshotlivepreview.cpp        | 28 +++++++++----
 indra/newview/skins/default/xui/en/strings.xml | 12 ++++++
 4 files changed, 73 insertions(+), 56 deletions(-)

diff --git a/indra/newview/llimagefiltersmanager.cpp b/indra/newview/llimagefiltersmanager.cpp
index 14177b4f05..0633dcaefc 100644
--- a/indra/newview/llimagefiltersmanager.cpp
+++ b/indra/newview/llimagefiltersmanager.cpp
@@ -1,6 +1,6 @@
 /** 
  * @file llimagefiltersmanager.cpp
- * @brief Load and execute image filters. Mostly used for Flickr at the moment.
+ * @brief Load image filters list and retrieve their path. Mostly used for Flickr UI at the moment.
  *
  * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -29,10 +29,15 @@
 #include "llimagefiltersmanager.h"
 
 #include "lldiriterator.h"
+#include "lltrans.h"
 
+std::string get_sys_dir()
+{
+	return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "filters", "");
+}
 
 //---------------------------------------------------------------------------
-// LLImageFilters
+// LLImageFiltersManager
 //---------------------------------------------------------------------------
 
 LLImageFiltersManager::LLImageFiltersManager()
@@ -49,16 +54,10 @@ void LLImageFiltersManager::initSingleton()
 	loadAllFilters();
 }
 
-// static
-std::string LLImageFiltersManager::getSysDir()
-{
-	return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "filters", "");
-}
-
 void LLImageFiltersManager::loadAllFilters()
 {
 	// Load system (coming out of the box) filters
-	loadFiltersFromDir(getSysDir());
+	loadFiltersFromDir(get_sys_dir());
 }
 
 void LLImageFiltersManager::loadFiltersFromDir(const std::string& dir)
@@ -68,29 +67,44 @@ void LLImageFiltersManager::loadFiltersFromDir(const std::string& dir)
 	LLDirIterator dir_iter(dir, "*.xml");
 	while (1)
 	{
-		std::string file;
-		if (!dir_iter.next(file))
+		std::string file_name;
+		if (!dir_iter.next(file_name))
 		{
 			break; // no more files
 		}
 		
-		// Get the ".xml" out of the file name to get the filter name
-		std::string filter_name = file.substr(0,file.length()-4);
-        mFiltersList.push_back(filter_name);
+		// Get the ".xml" out of the file name to get the filter name. That's the one known in strings.xml
+		std::string filter_name = file_name.substr(0,file_name.length()-4);
+        // Get the localized name for the filter
+		filter_name = LLTrans::getString(filter_name);
         
-		std::string path = gDirUtilp->add(dir, file);
-
-        // For the moment, just output the file found to the log
-        llinfos << "Merov : loadFiltersFromDir, filter = " << file << ",path = " << path << llendl;
+        mFiltersList[filter_name] = file_name;
 	}
 }
 
+// Note : That method is a bit heavy handed but the list of filters is always small (10 or so)
+// and that method is typically called only once when building UI widgets.
+const std::vector<std::string> LLImageFiltersManager::getFiltersList() const
+{
+    std::vector<std::string> filter_list;
+    for (std::map<std::string,std::string>::const_iterator it = mFiltersList.begin(); it != mFiltersList.end(); ++it)
+    {
+        filter_list.push_back(it->first);
+    }
+    return filter_list;
+}
+
 std::string LLImageFiltersManager::getFilterPath(const std::string& filter_name)
 {
-    // *TODO : we should store (filter name, path) in a std::map
-    std::string file = filter_name + ".xml";
-    std::string dir = getSysDir();
-    std::string path = gDirUtilp->add(dir, file);
+    std::string path = "";
+    std::map<std::string,std::string>::const_iterator it = mFiltersList.find(filter_name);
+    if (it != mFiltersList.end())
+    {
+        // Get the file name for that filter and build the complete path
+        std::string file = it->second;
+        std::string dir = get_sys_dir();
+        path = gDirUtilp->add(dir, file);
+    }
     return path;
 }
 
diff --git a/indra/newview/llimagefiltersmanager.h b/indra/newview/llimagefiltersmanager.h
index 5591e14a41..4751933065 100644
--- a/indra/newview/llimagefiltersmanager.h
+++ b/indra/newview/llimagefiltersmanager.h
@@ -1,6 +1,6 @@
 /** 
  * @file llimagefiltersmanager.h
- * @brief Load and execute image filters. Mostly used for Flickr at the moment.
+ * @brief Load image filters list and retrieve their path. Mostly used for Flickr UI at the moment.
  *
  * $LicenseInfo:firstyear=2000&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -28,49 +28,28 @@
 #define LL_LLIMAGEFILTERSMANAGER_H
 
 #include "llsingleton.h"
-#include "llimage.h"
-/*
-typedef enum e_vignette_mode
-{
-	VIGNETTE_MODE_NONE  = 0,
-	VIGNETTE_MODE_BLEND = 1,
-	VIGNETTE_MODE_FADE  = 2
-} EVignetteMode;
 
-typedef enum e_screen_mode
-{
-	SCREEN_MODE_2DSINE   = 0,
-	SCREEN_MODE_LINE     = 1
-} EScreenMode;
-*/
 //============================================================================
-// library initialization class
+// LLImageFiltersManager class
 
 class LLImageFiltersManager : public LLSingleton<LLImageFiltersManager>
 {
 	LOG_CLASS(LLImageFiltersManager);
 public:
-    // getFilters(); get a vector of std::string containing the filter names
-    //LLSD loadFilter(const std::string& filter_name);
-    //void executeFilter(const LLSD& filter_data, LLPointer<LLImageRaw> raw_image);
-    const std::vector<std::string> &getFiltersList() const { return mFiltersList; }
+    const std::vector<std::string> getFiltersList() const;
     std::string getFilterPath(const std::string& filter_name);
   
-protected:
 private:
 	void loadAllFilters();
 	void loadFiltersFromDir(const std::string& dir);
-//	LLSD loadFilter(const std::string& path);
-    
-	static std::string getSysDir();
     
     friend class LLSingleton<LLImageFiltersManager>;
 	/*virtual*/ void initSingleton();
 	LLImageFiltersManager();
 	~LLImageFiltersManager();
     
-	// List of filters
-    std::vector<std::string> mFiltersList;
+	// List of filters : first is the user friendly localized name, second is the xml file name
+    std::map<std::string,std::string> mFiltersList;
 };
 
 #endif // LL_LLIMAGEFILTERSMANAGER_H
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index c38798bbea..21abdd2675 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -591,11 +591,17 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
         // Filter the thumbnail
         if (getFilter() != "")
         {
-            LLImageFilter filter;
             std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter());
-            filter.loadFromFile(filter_path);
-            filter.executeFilter(raw);
-            //raw->filterGrayScale();
+            if (filter_path != "")
+            {
+                LLImageFilter filter;
+                filter.loadFromFile(filter_path);
+                filter.executeFilter(raw);
+            }
+            else
+            {
+                llwarns << "Couldn't find a path to the following filter : " << getFilter() << llendl;
+            }
         }
 		mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
 		mThumbnailUpToDate = TRUE ;
@@ -704,11 +710,17 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
             // Apply the filter to mPreviewImage
             if (previewp->getFilter() != "")
             {
-                LLImageFilter filter;
                 std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(previewp->getFilter());
-                filter.loadFromFile(filter_path);
-                filter.executeFilter(previewp->mPreviewImage);
-                //previewp->mPreviewImage->filterGrayScale();
+                if (filter_path != "")
+                {
+                    LLImageFilter filter;
+                    filter.loadFromFile(filter_path);
+                    filter.executeFilter(previewp->mPreviewImage);
+                }
+                else
+                {
+                    llwarns << "Couldn't find a path to the following filter : " << previewp->getFilter() << llendl;
+                }
             }
             
 			// delete any existing image
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index d226a72d7b..92913f678d 100755
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -168,6 +168,18 @@ Please try logging in again in a minute.</string>
   <string name="SocialTwitterErrorPosting">Problem posting to Twitter</string>
   <string name="SocialTwitterErrorDisconnecting">Problem disconnecting from Twitter</string>
     
+	<!-- SLShare: User Friendly Filter Names Translation -->
+    <string name="BlackAndWhite">Black &amp; White</string>
+    <string name="Colors1970">1970&apos;s Colors</string>
+    <string name="Heatwave">Heat Wave</string>
+    <string name="Intense">Intense</string>
+    <string name="JulesVerne">Jules Verne</string>
+    <string name="Newspaper">Newspaper</string>
+    <string name="Overcast">Overcast</string>
+    <string name="Sepia">Sepia</string>
+    <string name="Spotlight">Spotlight</string>
+    <string name="Video">Video</string>
+    
 	<!-- Tooltip -->
 	<string name="TooltipPerson">Person</string><!-- Object under mouse pointer is an avatar -->
 	<string name="TooltipNoName">(no name)</string> <!-- No name on an object -->
-- 
cgit v1.2.3


From fda7b94f490564568dee0ba6d6516943b0fd82a0 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Thu, 16 Jan 2014 18:34:51 -0800
Subject: ACME-1236 : Small LLImageFilter clean up

---
 .../llimage_libtest/llimage_libtest.cpp            | 14 ++++-----
 indra/llimage/llimagefilter.cpp                    | 33 +++++++---------------
 indra/llimage/llimagefilter.h                      |  6 ++--
 indra/newview/llfloaterflickr.cpp                  |  2 --
 indra/newview/llsnapshotlivepreview.cpp            |  6 ++--
 5 files changed, 21 insertions(+), 40 deletions(-)

diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index d3373a61f2..3d27b4a5b5 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -578,7 +578,10 @@ int main(int argc, char** argv)
 		fast_timer_log_thread = new LogThread(LLFastTimer::sLogName);
 		fast_timer_log_thread->start();
 	}
-	
+    
+    // Load the filter once and for all
+    LLImageFilter filter(filter_name);
+
 	// Perform action on each input file
 	std::list<std::string>::iterator in_file  = input_filenames.begin();
 	std::list<std::string>::iterator out_file = output_filenames.begin();
@@ -594,13 +597,8 @@ int main(int argc, char** argv)
 			continue;
 		}
         
-        if (filter_name != "")
-        {
-            // We're interpreting the filter as a filter file name
-            LLImageFilter filter;
-            filter.loadFromFile(filter_name);
-            filter.executeFilter(raw_image);
-        }
+        // Apply the filter
+        filter.executeFilter(raw_image);
 
 		// Save file
 		if (out_file != out_end)
diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index 5c969001b7..cd03454cdd 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -39,7 +39,7 @@
 // LLImageFilter
 //---------------------------------------------------------------------------
 
-LLImageFilter::LLImageFilter() :
+LLImageFilter::LLImageFilter(const std::string& file_path) :
     mFilterData(LLSD::emptyArray()),
     mImage(NULL),
     mHistoRed(NULL),
@@ -50,6 +50,15 @@ LLImageFilter::LLImageFilter() :
     mVignetteGamma(1.0),
     mVignetteMin(0.0)
 {
+    // Load filter description from file
+	llifstream filter_xml(file_path);
+	if (filter_xml.is_open())
+	{
+		// Load and parse the file
+		LLPointer<LLSDParser> parser = new LLSDXMLParser();
+		parser->parse(filter_xml, mFilterData, LLSDSerialize::SIZE_UNLIMITED);
+		filter_xml.close();
+	}
 }
 
 LLImageFilter::~LLImageFilter()
@@ -113,28 +122,6 @@ LLImageFilter::~LLImageFilter()
  "        - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n"
  */
 
-//============================================================================
-// Load filter from file
-//============================================================================
-
-void LLImageFilter::loadFromFile(const std::string& file_path)
-{
-	//std::cout << "Loading filter settings from : " << file_path << std::endl;
-	llifstream filter_xml(file_path);
-	if (filter_xml.is_open())
-	{
-		// Load and parse the file
-		LLPointer<LLSDParser> parser = new LLSDXMLParser();
-		parser->parse(filter_xml, mFilterData, LLSDSerialize::SIZE_UNLIMITED);
-		filter_xml.close();
-	}
-	else
-	{
-        // File couldn't be open, reset the filter data
-		mFilterData = LLSD();
-	}
-}
-
 //============================================================================
 // Apply the filter data to the image passed as parameter
 //============================================================================
diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h
index c67789ede0..dc092a47a5 100755
--- a/indra/llimage/llimagefilter.h
+++ b/indra/llimage/llimagefilter.h
@@ -54,15 +54,15 @@ typedef enum e_screen_mode
 } EScreenMode;
 
 //============================================================================
-// Image Filter 
+// LLImageFilter 
+//============================================================================
 
 class LLImageFilter
 {
 public:
-    LLImageFilter();
+    LLImageFilter(const std::string& file_path);
     ~LLImageFilter();
     
-    void loadFromFile(const std::string& file_path);
     void executeFilter(LLPointer<LLImageRaw> raw_image);
     
 private:
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index cff57bfa13..c34124caf5 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -334,7 +334,6 @@ void LLFlickrPhotoPanel::updateResolution(BOOL do_update)
 	S32 height = sdres[1];
     
     const std::string& filter_name = filterbox->getSimple();
-    llinfos << "Merov : filter name is : " << filter_name << llendl;
 
 	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
 	if (previewp && combobox->getCurrentIndex() >= 0)
@@ -358,7 +357,6 @@ void LLFlickrPhotoPanel::updateResolution(BOOL do_update)
 		checkAspectRatio(width);
 
 		previewp->getSize(width, height);
-        // Merov : 
         // Get the old filter, compare to the current one "filter_name" and set if changed
         // If changed, also force the updateSnapshot() here under
         std::string original_filter = previewp->getFilter();
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 21abdd2675..ee74dbdb0f 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -594,8 +594,7 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
             std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter());
             if (filter_path != "")
             {
-                LLImageFilter filter;
-                filter.loadFromFile(filter_path);
+                LLImageFilter filter(filter_path);
                 filter.executeFilter(raw);
             }
             else
@@ -713,8 +712,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
                 std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(previewp->getFilter());
                 if (filter_path != "")
                 {
-                    LLImageFilter filter;
-                    filter.loadFromFile(filter_path);
+                    LLImageFilter filter(filter_path);
                     filter.executeFilter(previewp->mPreviewImage);
                 }
                 else
-- 
cgit v1.2.3


From 95bb14440e4e35c7cc5c44a2b836deadb54bfd1b Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Fri, 17 Jan 2014 16:50:35 -0800
Subject: ACME-1236 : Refactor vignette into stencil, implement uniform and
 gradient stencils, implement dodge and add blend modes

---
 indra/llimage/llimagefilter.cpp | 308 +++++++++++++++++++++++++---------------
 indra/llimage/llimagefilter.h   |  55 ++++---
 2 files changed, 226 insertions(+), 137 deletions(-)

diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index cd03454cdd..03eabce8e3 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -46,9 +46,11 @@ LLImageFilter::LLImageFilter(const std::string& file_path) :
     mHistoGreen(NULL),
     mHistoBlue(NULL),
     mHistoBrightness(NULL),
-    mVignetteMode(VIGNETTE_MODE_NONE),
-    mVignetteGamma(1.0),
-    mVignetteMin(0.0)
+    mStencilBlendMode(STENCIL_BLEND_MODE_BLEND),
+    mStencilShape(STENCIL_SHAPE_UNIFORM),
+    mStencilGamma(1.0),
+    mStencilMin(0.0),
+    mStencilMax(1.0)
 {
     // Load filter description from file
 	llifstream filter_xml(file_path);
@@ -79,23 +81,13 @@ LLImageFilter::~LLImageFilter()
  * Add stencil (min,max) range
  * Suppress alpha from colorcorrect and use uniform alpha instead
  * Refactor stencil composition in the filter primitives
+ * Make filter definition resolution independent (do not use pixel size anywhere)
  
- <array>
- <string>stencil</string>
- <string>shape</string>
- <string>blend_mode</string>
- <real>min</real>
- <real>max</real>
- <real>param1</real>
- <real>param2</real>
- <real>param3</real>
- <real>param4</real>
- </array>
- 
- vignette : center_x, center_y, width, feather
- sine : wavelength, angle
- flat
- gradient : start_x, start_y, end_x, end_y
+ params:
+ * vignette : center_x, center_y, width, feather
+ * scan lines : wavelength, angle
+ * uniform
+ * gradient : start_x, start_y, end_x, end_y
 
  * Document all the admissible names in the wiki
  
@@ -143,17 +135,86 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
         //std::cout << std::endl;
         
         // Execute the filter described on this line
-        if (filter_name == "blend")
+        /*
+        <array>
+        <string>stencil</string> 
+        <string>shape</string> uniform / gradient / vignette / scanlines
+        <string>blend_mode</string> blend /add /dodge / fade
+        <real>min</real> -1.0 to 1.0 (mandatory though ignored for uniform shape)
+        <real>max</real> -1.0 to 1.0 (value for uniform)
+        <real>param1</real>
+        <real>param2</real>
+        <real>param3</real>
+        <real>param4</real>
+        </array>
+         params:
+         * vignette : center_x, center_y, width, feather : positions between in float (0.0 is center, 1.0 is top), width in float in same unit, feather is a float
+         * scan lines : wavelength, angle : wavelength in float assuming (height/2 = 1), angle float in degree
+         * uniform : all parameters ignored
+         * gradient : start_x, start_y, end_x, end_y : position in float (0.0 is center, 1.0 is top)
+         */
+        if (filter_name == "stencil")
         {
-            setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()));
+            // Get the shape of the stencil, that is how the procedural alpha is computed geometrically
+            std::string filter_shape = mFilterData[i][1].asString();
+            EStencilShape shape = STENCIL_SHAPE_UNIFORM;
+            if (filter_shape == "uniform")
+            {
+                shape = STENCIL_SHAPE_UNIFORM;
+            }
+            else if (filter_shape == "gradient")
+            {
+                shape = STENCIL_SHAPE_GRADIENT;
+            }
+            else if (filter_shape == "vignette")
+            {
+                shape = STENCIL_SHAPE_VIGNETTE;
+            }
+            else if (filter_shape == "scanlines")
+            {
+                shape = STENCIL_SHAPE_SCAN_LINES;
+            }
+            // Get the blend mode of the stencil, that is how the effect is blended in the background through the alpha
+            std::string filter_mode  = mFilterData[i][2].asString();
+            EStencilBlendMode mode = STENCIL_BLEND_MODE_BLEND;
+            if (filter_mode == "blend")
+            {
+                mode = STENCIL_BLEND_MODE_BLEND;
+            }
+            else if (filter_mode == "add")
+            {
+                mode = STENCIL_BLEND_MODE_ADD;
+            }
+            else if (filter_mode == "dodge")
+            {
+                mode = STENCIL_BLEND_MODE_DODGE;
+            }
+            else if (filter_mode == "fade")
+            {
+                mode = STENCIL_BLEND_MODE_FADE;
+            }
+            // Get the float params: mandatory min, max then the optional parameters (4 max)
+            F32 min = (F32)(mFilterData[i][3].asReal());
+            F32 max = (F32)(mFilterData[i][4].asReal());
+            F32 params[4] = {0.0, 0.0, 0.0, 0.0};
+            for (S32 j = 5; (j < mFilterData[i].size()) && (j < 9); j++)
+            {
+                params[j-5] = (F32)(mFilterData[i][j].asReal());
+            }
+            // Set the stencil
+            setStencil(shape,mode,min,max,params);
+        }
+        else if (filter_name == "blend")
+        {
+            setStencil(STENCIL_BLEND_MODE_BLEND,STENCIL_SHAPE_VIGNETTE,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0);
         }
         else if (filter_name == "fade")
         {
-            setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()));
+            setStencil(STENCIL_BLEND_MODE_FADE,STENCIL_SHAPE_VIGNETTE,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0);
         }
         else if (filter_name == "lines")
         {
-            setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()));
+            setStencil(STENCIL_BLEND_MODE_BLEND,STENCIL_SHAPE_SCAN_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0);
         }
         else if (filter_name == "sepia")
         {
@@ -228,6 +289,38 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
 // Filter Primitives
 //============================================================================
 
+void LLImageFilter::blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue)
+{
+    F32 inv_alpha = 1.0 - alpha;
+    switch (mStencilBlendMode)
+    {
+        case STENCIL_BLEND_MODE_BLEND:
+            // Classic blend of incoming color with the background image
+            pixel[VRED]   = inv_alpha * pixel[VRED]   + alpha * red;
+            pixel[VGREEN] = inv_alpha * pixel[VGREEN] + alpha * green;
+            pixel[VBLUE]  = inv_alpha * pixel[VBLUE]  + alpha * blue;
+            break;
+        case STENCIL_BLEND_MODE_ADD:
+            // Add incoming color to the background image
+            pixel[VRED]   = pixel[VRED]   + alpha * red;
+            pixel[VGREEN] = pixel[VGREEN] + alpha * green;
+            pixel[VBLUE]  = pixel[VBLUE]  + alpha * blue;
+            break;
+        case STENCIL_BLEND_MODE_DODGE:
+            // Dodge/burn the incoming color onto the background image
+            pixel[VRED]   = inv_alpha * pixel[VRED]   + red;
+            pixel[VGREEN] = inv_alpha * pixel[VGREEN] + green;
+            pixel[VBLUE]  = inv_alpha * pixel[VBLUE]  + blue;
+            break;
+        case STENCIL_BLEND_MODE_FADE:
+            // Fade incoming color to black
+            pixel[VRED]   = alpha * red;
+            pixel[VGREEN] = alpha * green;
+            pixel[VBLUE]  = alpha * blue;
+            break;
+    }
+}
+
 void LLImageFilter::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue)
 {
 	const S32 components = mImage->getComponents();
@@ -241,31 +334,8 @@ void LLImageFilter::colorCorrect(const U8* lut_red, const U8* lut_green, const U
 	{
         for (S32 i = 0; i < width; i++)
         {
-            if (mVignetteMode == VIGNETTE_MODE_NONE)
-            {
-                dst_data[VRED]   = lut_red[dst_data[VRED]];
-                dst_data[VGREEN] = lut_green[dst_data[VGREEN]];
-                dst_data[VBLUE]  = lut_blue[dst_data[VBLUE]];
-            }
-            else
-            {
-                F32 alpha = getVignetteAlpha(i,j);
-                if (mVignetteMode == VIGNETTE_MODE_BLEND)
-                {
-                    // Blends with the source image on the edges
-                    F32 inv_alpha = 1.0 - alpha;
-                    dst_data[VRED]   = inv_alpha * dst_data[VRED]  + alpha * lut_red[dst_data[VRED]];
-                    dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * lut_green[dst_data[VGREEN]];
-                    dst_data[VBLUE]  = inv_alpha * dst_data[VBLUE]  + alpha * lut_blue[dst_data[VBLUE]];
-                }
-                else // VIGNETTE_MODE_FADE
-                {
-                    // Fade to black on the edges
-                    dst_data[VRED]   = alpha * lut_red[dst_data[VRED]];
-                    dst_data[VGREEN] = alpha * lut_green[dst_data[VGREEN]];
-                    dst_data[VBLUE]  = alpha * lut_blue[dst_data[VBLUE]];
-                }
-            }
+            // Blend LUT value
+            blendStencil(getStencilAlpha(i,j), dst_data, lut_red[dst_data[VRED]], lut_green[dst_data[VGREEN]], lut_blue[dst_data[VBLUE]]);
             dst_data += components;
         }
 	}
@@ -284,34 +354,13 @@ void LLImageFilter::colorTransform(const LLMatrix3 &transform)
 	{
         for (S32 i = 0; i < width; i++)
         {
+            // Compute transform
             LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE]));
             LLVector3 dst = src * transform;
             dst.clamp(0.0f,255.0f);
-            if (mVignetteMode == VIGNETTE_MODE_NONE)
-            {
-                dst_data[VRED]   = dst.mV[VRED];
-                dst_data[VGREEN] = dst.mV[VGREEN];
-                dst_data[VBLUE]  = dst.mV[VBLUE];
-            }
-            else
-            {
-                F32 alpha = getVignetteAlpha(i,j);
-                if (mVignetteMode == VIGNETTE_MODE_BLEND)
-                {
-                    // Blends with the source image on the edges
-                    F32 inv_alpha = 1.0 - alpha;
-                    dst_data[VRED]   = inv_alpha * src.mV[VRED]   + alpha * dst.mV[VRED];
-                    dst_data[VGREEN] = inv_alpha * src.mV[VGREEN] + alpha * dst.mV[VGREEN];
-                    dst_data[VBLUE]  = inv_alpha * src.mV[VBLUE]  + alpha * dst.mV[VBLUE];
-                }
-                else // VIGNETTE_MODE_FADE
-                {
-                    // Fade to black on the edges
-                    dst_data[VRED]   = alpha * dst.mV[VRED];
-                    dst_data[VGREEN] = alpha * dst.mV[VGREEN];
-                    dst_data[VBLUE]  = alpha * dst.mV[VBLUE];
-                }
-            }
+            
+            // Blend result
+            blendStencil(getStencilAlpha(i,j), dst_data, dst.mV[VRED], dst.mV[VGREEN], dst.mV[VBLUE]);
             dst_data += components;
         }
 	}
@@ -333,6 +382,7 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const
 	{
         for (S32 i = 0; i < width; i++)
         {
+            // Compute screen value
             F32 value = 0.0;
             F32 d = 0.0;
             switch (mode)
@@ -347,31 +397,8 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const
             }
             U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0);
             
-            if (mVignetteMode == VIGNETTE_MODE_NONE)
-            {
-                dst_data[VRED]   = dst_value;
-                dst_data[VGREEN] = dst_value;
-                dst_data[VBLUE]  = dst_value;
-            }
-            else
-            {
-                F32 alpha = getVignetteAlpha(i,j);
-                if (mVignetteMode == VIGNETTE_MODE_BLEND)
-                {
-                    // Blends with the source image on the edges
-                    F32 inv_alpha = 1.0 - alpha;
-                    dst_data[VRED]   = inv_alpha * dst_data[VRED]   + alpha * dst_value;
-                    dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * dst_value;
-                    dst_data[VBLUE]  = inv_alpha * dst_data[VBLUE]  + alpha * dst_value;
-                }
-                else // VIGNETTE_MODE_FADE
-                {
-                    // Fade to black on the edges
-                    dst_data[VRED]   = alpha * dst_value;
-                    dst_data[VGREEN] = alpha * dst_value;
-                    dst_data[VBLUE]  = alpha * dst_value;
-                }
-            }
+            // Blend result
+            blendStencil(getStencilAlpha(i,j), dst_data, dst_value, dst_value, dst_value);
             dst_data += components;
         }
 	}
@@ -381,36 +408,81 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const
 // Procedural Stencils
 //============================================================================
 
-void LLImageFilter::setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min)
+void LLImageFilter::setStencil(EStencilBlendMode mode, EStencilShape type, F32 gamma, F32 min, F32 max)
 {
-    mVignetteMode = mode;
-    mVignetteType = type;
-    mVignetteGamma = gamma;
-    mVignetteMin = llclampf(min);
-    // We always center the vignette on the image and fits it in the image smallest dimension
-    mVignetteCenterX = mImage->getWidth()/2;
-    mVignetteCenterY = mImage->getHeight()/2;
-    mVignetteWidth = llmin(mImage->getWidth()/2,mImage->getHeight()/2);
+    mStencilBlendMode = mode;
+    mStencilShape = type;
+    mStencilGamma = gamma;
+    mStencilMin = llmin(llmax(min, -1.0f), 1.0f);
+    mStencilMax = llmin(llmax(max, -1.0f), 1.0f);
+
+    // We center the vignette on the image and fits it in the image smallest dimension
+    mStencilCenterX = mImage->getWidth()/2;
+    mStencilCenterY = mImage->getHeight()/2;
+    mStencilWidth = llmin(mImage->getWidth()/2,mImage->getHeight()/2);
+    
+    mStencilWavelength = gamma;
+    mStencilSine   = 0.0;
+    mStencilCosine = 1.0;
+    
+    mStencilStartX = 0.0;
+    mStencilStartY = 0.0;
+    mStencilGradX  = 0.0;
+    mStencilGradY  = (F32)(mImage->getHeight());
+    mStencilGradN  = (F32)(mImage->getHeight()*mImage->getHeight());
 }
 
-F32 LLImageFilter::getVignetteAlpha(S32 i, S32 j)
+void LLImageFilter::setStencil(EStencilShape shape, EStencilBlendMode mode, F32 min, F32 max, F32* params)
 {
-    F32 alpha = 1.0;
-    if (mVignetteType == VIGNETTE_TYPE_CENTER)
+    mStencilShape = shape;
+    mStencilBlendMode = mode;
+    mStencilMin = llmin(llmax(min, -1.0f), 1.0f);
+    mStencilMax = llmin(llmax(max, -1.0f), 1.0f);
+    
+    // Each shape will interpret the 4 params differenly.
+    // We compute each systematically, though, clearly, values are meaningless when the shape doesn't correspond to the parameters
+    mStencilCenterX = (S32)(mImage->getWidth()  + params[0] * (F32)(mImage->getHeight()))/2;
+    mStencilCenterY = (S32)(mImage->getHeight() + params[1] * (F32)(mImage->getHeight()))/2;
+    mStencilWidth = (S32)(params[2] * (F32)(mImage->getHeight()))/2;
+    mStencilGamma = (params[3] <= 0.0 ? 1.0 : params[3]);
+
+    mStencilWavelength = (params[0] <= 0.0 ? 10.0 : params[0] * (F32)(mImage->getHeight()) / 2.0);
+    mStencilSine   = sinf(params[1]*DEG_TO_RAD);
+    mStencilCosine = cosf(params[1]*DEG_TO_RAD);
+
+    mStencilStartX = ((F32)(mImage->getWidth())  + params[0] * (F32)(mImage->getHeight()))/2.0;
+    mStencilStartY = ((F32)(mImage->getHeight()) + params[1] * (F32)(mImage->getHeight()))/2.0;
+    F32 end_x      = ((F32)(mImage->getWidth())  + params[2] * (F32)(mImage->getHeight()))/2.0;
+    F32 end_y      = ((F32)(mImage->getHeight()) + params[3] * (F32)(mImage->getHeight()))/2.0;
+    mStencilGradX  = end_x - mStencilStartX;
+    mStencilGradY  = end_y - mStencilStartY;
+    mStencilGradN  = mStencilGradX*mStencilGradX + mStencilGradY*mStencilGradY;
+}
+
+F32 LLImageFilter::getStencilAlpha(S32 i, S32 j)
+{
+    F32 alpha = 1.0;    // That init actually takes care of the STENCIL_SHAPE_UNIFORM case...
+    if (mStencilShape == STENCIL_SHAPE_VIGNETTE)
     {
         // alpha is a modified gaussian value, with a center and fading in a circular pattern toward the edges
         // The gamma parameter controls the intensity of the drop down from alpha 1.0 (center) to 0.0
-        F32 d_center_square = (i - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY);
-        alpha = powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f));
+        F32 d_center_square = (i - mStencilCenterX)*(i - mStencilCenterX) + (j - mStencilCenterY)*(j - mStencilCenterY);
+        alpha = powf(F_E, -(powf((d_center_square/(mStencilWidth*mStencilWidth)),mStencilGamma)/2.0f));
     }
-    else if (mVignetteType == VIGNETTE_TYPE_LINES)
+    else if (mStencilShape == STENCIL_SHAPE_SCAN_LINES)
     {
-        // alpha varies according to a squared sine function vertically.
-        // gamma is interpreted as the wavelength (in pixels) of the sine in that case.
-        alpha = (sinf(2*F_PI*j/mVignetteGamma) > 0.0 ? 1.0 : 0.0);
+        // alpha varies according to a squared sine function.
+        F32 d = mStencilSine*i - mStencilCosine*j;
+        alpha = (sinf(2*F_PI*d/mStencilWavelength) > 0.0 ? 1.0 : 0.0);
     }
-    // We rescale alpha between min and 1.0 so to avoid complete fading if so desired.
-    return (mVignetteMin + alpha * (1.0 - mVignetteMin));
+    else if (mStencilShape == STENCIL_SHAPE_GRADIENT)
+    {
+        alpha = (((F32)(i) - mStencilStartX)*mStencilGradX + ((F32)(j) - mStencilStartY)*mStencilGradY) / mStencilGradN;
+        alpha = llclampf(alpha);
+    }
+    
+    // We rescale alpha between min and max
+    return (mStencilMin + alpha * (mStencilMax - mStencilMin));
 }
 
 //============================================================================
diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h
index dc092a47a5..19ac7e81d6 100755
--- a/indra/llimage/llimagefilter.h
+++ b/indra/llimage/llimagefilter.h
@@ -34,18 +34,21 @@ class LLColor4U;
 class LLColor3;
 class LLMatrix3;
 
-typedef enum e_vignette_mode
+typedef enum e_stencil_blend_mode
 {
-	VIGNETTE_MODE_NONE  = 0,
-	VIGNETTE_MODE_BLEND = 1,
-	VIGNETTE_MODE_FADE  = 2
-} EVignetteMode;
+	STENCIL_BLEND_MODE_BLEND = 0,
+	STENCIL_BLEND_MODE_ADD   = 1,
+	STENCIL_BLEND_MODE_DODGE = 2,
+	STENCIL_BLEND_MODE_FADE  = 3
+} EStencilBlendMode;
 
-typedef enum e_vignette_type
+typedef enum e_stencil_shape
 {
-	VIGNETTE_TYPE_CENTER = 0,
-	VIGNETTE_TYPE_LINES  = 1
-} EVignetteType;
+	STENCIL_SHAPE_UNIFORM    = 0,
+	STENCIL_SHAPE_GRADIENT   = 1,
+	STENCIL_SHAPE_VIGNETTE   = 2,
+	STENCIL_SHAPE_SCAN_LINES = 3
+} EStencilShape;
 
 typedef enum e_screen_mode
 {
@@ -87,10 +90,12 @@ private:
     void colorTransform(const LLMatrix3 &transform);
     void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue);
     void filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle);
+    void blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue);
 
     // Procedural Stencils
-    void setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min);
-    F32 getVignetteAlpha(S32 i, S32 j);
+    void setStencil(EStencilBlendMode mode, EStencilShape type, F32 gamma, F32 min, F32 max);
+    void setStencil(EStencilShape shape, EStencilBlendMode mode, F32 min, F32 max, F32* params);
+    F32 getStencilAlpha(S32 i, S32 j);
 
     // Histograms
     U32* getBrightnessHistogram();
@@ -105,14 +110,26 @@ private:
     U32 *mHistoBlue;
     U32 *mHistoBrightness;
     
-    // Vignette filtering
-    EVignetteMode mVignetteMode;
-    EVignetteType mVignetteType;
-    S32 mVignetteCenterX;
-    S32 mVignetteCenterY;
-    S32 mVignetteWidth;
-    F32 mVignetteGamma;
-    F32 mVignetteMin;
+    // Current Stencil Settings
+    EStencilBlendMode mStencilBlendMode;
+    EStencilShape mStencilShape;
+    F32 mStencilMin;
+    F32 mStencilMax;
+    
+    S32 mStencilCenterX;
+    S32 mStencilCenterY;
+    S32 mStencilWidth;
+    F32 mStencilGamma;
+    
+    F32 mStencilWavelength;
+    F32 mStencilSine;
+    F32 mStencilCosine;
+    
+    F32 mStencilStartX;
+    F32 mStencilStartY;
+    F32 mStencilGradX;
+    F32 mStencilGradY;
+    F32 mStencilGradN;
 };
 
 
-- 
cgit v1.2.3


From d14392f55f9c47ba121d5470a3deb153a16b1cfb Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Mon, 20 Jan 2014 19:52:27 -0800
Subject: ACME-1236 : Fix new blend modes, updated comments

---
 indra/llimage/llimagefilter.cpp | 43 ++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 22 deletions(-)

diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index 03eabce8e3..0f11b1037f 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -74,14 +74,12 @@ LLImageFilter::~LLImageFilter()
 
 /*
  *TODO 
- * Rename vignette to stencil
- * Separate shape from mode
- * Add shapes : uniform and gradients
- * Add modes
- * Add stencil (min,max) range
- * Suppress alpha from colorcorrect and use uniform alpha instead
- * Refactor stencil composition in the filter primitives
+ * Test blend modes
+ * Improve perf: use LUT for alpha blending in uniform case
+ * Improve perf: make sure filter is not called more than necessary in viewer (seems to be called 3 times per change)
  * Make filter definition resolution independent (do not use pixel size anywhere)
+ * Add gradient coloring as a filter
+ * Add convolve3x3
  
  params:
  * vignette : center_x, center_y, width, feather
@@ -96,18 +94,19 @@ LLImageFilter::~LLImageFilter()
  "        - 'sepia' converts to sepia (no param).\n"
  "        - 'saturate' changes color saturation according to <param>: < 1.0 will desaturate, > 1.0 will saturate.\n"
  "        - 'rotate' rotates the color hue according to <param> (in degree, positive value only).\n"
- "        - 'gamma' applies gamma curve <param> to all channels: > 1.0 will darken, < 1.0 will lighten.\n"
- "        - 'colorize' applies a red tint to the image using <param> as an alpha (transparency between 0.0 and 1.0) value.\n"
+ 
+ "        - 'gamma' applies a gamma curve <param> to all channels: > 1.0 will darken, < 1.0 will lighten.\n"
+ "        - 'colorize' applies a colored tint <param1, param2, param3> to the image.\n"
  "        - 'contrast' modifies the contrast according to <param> : > 1.0 will enhance the contrast, <1.0 will flatten it.\n"
  "        - 'brighten' adds <param> light to the image (<param> between 0 and 255).\n"
  "        - 'darken' substracts <param> light to the image (<param> between 0 and 255).\n"
- "        - 'linearize' optimizes the contrast using the brightness histogram. <param> is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n"
+ "        - 'linearize' optimizes the contrast using the brightness histogram. <param> is the fraction (between 0.0 and 1.0) of the discarded head and tail of the histogram.\n"
  "        - 'posterize' redistributes the colors between <param> classes per channel (<param> between 2 and 255).\n"
- "        - 'newsscreen' applies a 2D sine screening to the red channel and output to black and white.\n"
- "        - 'horizontalscreen' applies a horizontal screening to the red channel and output to black and white.\n"
- "        - 'verticalscreen' applies a vertical screening to the red channel and output to black and white.\n"
- "        - 'slantedscreen' applies a 45 degrees slanted screening to the red channel and output to black and white.\n"
- "        - Any other value will be interpreted as a file name describing a sequence of filters and parameters to be applied to the input images.\n"
+ 
+ "        - 'screen' applies a screening filter to the red channel and output to black and white. This filter assumes that the input image has been converted to grayscale or that the red channel is somewhat meaningful. It takes 3 parameters: a mode, a wave length and an angle. Modes are:\n"
+ "            - '2Dsine' applies a bidirectional (x,y) sine screen. <angle> has no influence on that mode.\n"
+ "            - 'line' applies a linear sine screen. <angle> is the line generator angle with the horizontal.\n"
+ "         <wave_length> is size between 2 peaks of the sine function in normalized image coordinates."
 
  "        Apply a circular central vignette <name> to the filter using the optional <feather> and <min> values. Admissible names:\n"
  "        - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n"
@@ -174,7 +173,7 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
             {
                 shape = STENCIL_SHAPE_SCAN_LINES;
             }
-            // Get the blend mode of the stencil, that is how the effect is blended in the background through the alpha
+            // Get the blend mode of the stencil, that is how the effect is blended in the background through the stencil
             std::string filter_mode  = mFilterData[i][2].asString();
             EStencilBlendMode mode = STENCIL_BLEND_MODE_BLEND;
             if (filter_mode == "blend")
@@ -302,15 +301,15 @@ void LLImageFilter::blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue
             break;
         case STENCIL_BLEND_MODE_ADD:
             // Add incoming color to the background image
-            pixel[VRED]   = pixel[VRED]   + alpha * red;
-            pixel[VGREEN] = pixel[VGREEN] + alpha * green;
-            pixel[VBLUE]  = pixel[VBLUE]  + alpha * blue;
+            pixel[VRED]   = llclampb(pixel[VRED]   + alpha * red);
+            pixel[VGREEN] = llclampb(pixel[VGREEN] + alpha * green);
+            pixel[VBLUE]  = llclampb(pixel[VBLUE]  + alpha * blue);
             break;
         case STENCIL_BLEND_MODE_DODGE:
             // Dodge/burn the incoming color onto the background image
-            pixel[VRED]   = inv_alpha * pixel[VRED]   + red;
-            pixel[VGREEN] = inv_alpha * pixel[VGREEN] + green;
-            pixel[VBLUE]  = inv_alpha * pixel[VBLUE]  + blue;
+            pixel[VRED]   = llclampb(inv_alpha * pixel[VRED]   + red);
+            pixel[VGREEN] = llclampb(inv_alpha * pixel[VGREEN] + green);
+            pixel[VBLUE]  = llclampb(inv_alpha * pixel[VBLUE]  + blue);
             break;
         case STENCIL_BLEND_MODE_FADE:
             // Fade incoming color to black
-- 
cgit v1.2.3


From 6c630b73a825befb6eeef66d7ed0063b1b891df7 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 21 Jan 2014 13:05:54 -0800
Subject: ACME-1240 : Implement convolve filter for 3x3 kernels. Implements
 sharpen, blur and edge detection as examples and tests.

---
 indra/integration_tests/llimage_libtest/blur.xml   |   7 +
 indra/integration_tests/llimage_libtest/edges.xml  |  24 +++
 .../integration_tests/llimage_libtest/sharpen.xml  |   7 +
 indra/llimage/llimagefilter.cpp                    | 164 +++++++++++++++++++++
 indra/llimage/llimagefilter.h                      |   1 +
 5 files changed, 203 insertions(+)
 create mode 100644 indra/integration_tests/llimage_libtest/blur.xml
 create mode 100644 indra/integration_tests/llimage_libtest/edges.xml
 create mode 100644 indra/integration_tests/llimage_libtest/sharpen.xml

diff --git a/indra/integration_tests/llimage_libtest/blur.xml b/indra/integration_tests/llimage_libtest/blur.xml
new file mode 100644
index 0000000000..addd056855
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/blur.xml
@@ -0,0 +1,7 @@
+<llsd>
+    <array>
+        <array>
+            <string>blur</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/edges.xml b/indra/integration_tests/llimage_libtest/edges.xml
new file mode 100644
index 0000000000..a66b81d01e
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/edges.xml
@@ -0,0 +1,24 @@
+<llsd>
+    <array>
+        <array>
+            <string>gradient</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>2.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/sharpen.xml b/indra/integration_tests/llimage_libtest/sharpen.xml
new file mode 100644
index 0000000000..6d3f9ae1a2
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/sharpen.xml
@@ -0,0 +1,7 @@
+<llsd>
+    <array>
+        <array>
+            <string>sharpen</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index 0f11b1037f..75661a6d4b 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -34,6 +34,7 @@
 #include "m3math.h"
 #include "v3math.h"
 #include "llsdserialize.h"
+#include "llstring.h"
 
 //---------------------------------------------------------------------------
 // LLImageFilter
@@ -281,6 +282,32 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
             }
             filterScreen(mode,(S32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal()));
         }
+        else if (filter_name == "blur")
+        {
+            LLMatrix3 kernel;
+            for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++)
+                for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+                    kernel.mMatrix[i][j] = 1.0;
+            convolve(kernel,true,false);
+        }
+        else if (filter_name == "sharpen")
+        {
+            LLMatrix3 kernel;
+            for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++)
+                for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+                    kernel.mMatrix[i][j] = -1.0;
+            kernel.mMatrix[1][1] = 9.0;
+            convolve(kernel,false,false);
+        }
+        else if (filter_name == "gradient")
+        {
+            LLMatrix3 kernel;
+            for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++)
+                for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+                    kernel.mMatrix[i][j] = -1.0;
+            kernel.mMatrix[1][1] = 8.0;
+            convolve(kernel,false,true);
+        }
     }
 }
 
@@ -365,6 +392,143 @@ void LLImageFilter::colorTransform(const LLMatrix3 &transform)
 	}
 }
 
+void LLImageFilter::convolve(const LLMatrix3 &kernel, bool normalize, bool abs_value)
+{
+	const S32 components = mImage->getComponents();
+	llassert( components >= 1 && components <= 4 );
+    
+    // Compute normalization factors
+    F32 kernel_min = 0.0;
+    F32 kernel_max = 0.0;
+    for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++)
+    {
+        for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+        {
+            if (kernel.mMatrix[i][j] >= 0.0)
+                kernel_max += kernel.mMatrix[i][j];
+            else
+                kernel_min += kernel.mMatrix[i][j];
+        }
+    }
+    if (abs_value)
+    {
+        kernel_max = llabs(kernel_max);
+        kernel_min = llabs(kernel_min);
+        kernel_max = llmax(kernel_max,kernel_min);
+        kernel_min = 0.0;
+    }
+    F32 kernel_range = kernel_max - kernel_min;
+    
+    // Allocate temporary buffers and initialize algorithm's data
+	S32 width  = mImage->getWidth();
+    S32 height = mImage->getHeight();
+    
+	U8* dst_data = mImage->getData();
+
+	S32 buffer_size = width * components;
+	llassert_always(buffer_size > 0);
+	std::vector<U8> even_buffer(buffer_size);
+	std::vector<U8> odd_buffer(buffer_size);
+	
+    U8* south_data = dst_data + buffer_size;
+    U8* east_west_data;
+    U8* north_data;
+    
+    // Line 0 : we set the line to 0 (debatable)
+    memcpy( &even_buffer[0], dst_data, buffer_size );	/* Flawfinder: ignore */
+    for (S32 i = 0; i < width; i++)
+    {
+        blendStencil(getStencilAlpha(i,0), dst_data, 0, 0, 0);
+        dst_data += components;
+    }
+    south_data += buffer_size;
+    
+    // All other lines
+    for (S32 j = 1; j < (height-1); j++)
+	{
+        // We need to buffer 2 lines. We flip north and current to avoid moving too much memory around
+        if (j % 2)
+        {
+            memcpy( &odd_buffer[0], dst_data, buffer_size );	/* Flawfinder: ignore */
+            east_west_data = &odd_buffer[0];
+            north_data = &even_buffer[0];
+        }
+        else
+        {
+            memcpy( &even_buffer[0], dst_data, buffer_size );	/* Flawfinder: ignore */
+            east_west_data = &even_buffer[0];
+            north_data = &odd_buffer[0];
+        }
+        // First pixel : set to 0
+        blendStencil(getStencilAlpha(0,j), dst_data, 0, 0, 0);
+        // Set pointers to kernel
+        U8* NW = north_data;
+        U8* N = NW+components;
+        U8* NE = N+components;
+        U8* W = east_west_data;
+        U8* C = W+components;
+        U8* E = C+components;
+        U8* SW = south_data;
+        U8* S = SW+components;
+        U8* SE = S+components;
+        dst_data += components;
+        // All other pixels
+        for (S32 i = 1; i < (width-1); i++)
+        {
+            // Compute convolution
+            LLVector3 dst;
+            dst.mV[VRED] = (kernel.mMatrix[0][0]*NW[VRED] + kernel.mMatrix[0][1]*N[VRED] + kernel.mMatrix[0][2]*NE[VRED] +
+                            kernel.mMatrix[1][0]*W[VRED]  + kernel.mMatrix[1][1]*C[VRED] + kernel.mMatrix[1][2]*E[VRED] +
+                            kernel.mMatrix[2][0]*SW[VRED] + kernel.mMatrix[2][1]*S[VRED] + kernel.mMatrix[2][2]*SE[VRED]);
+            dst.mV[VGREEN] = (kernel.mMatrix[0][0]*NW[VGREEN] + kernel.mMatrix[0][1]*N[VGREEN] + kernel.mMatrix[0][2]*NE[VGREEN] +
+                              kernel.mMatrix[1][0]*W[VGREEN]  + kernel.mMatrix[1][1]*C[VGREEN] + kernel.mMatrix[1][2]*E[VGREEN] +
+                              kernel.mMatrix[2][0]*SW[VGREEN] + kernel.mMatrix[2][1]*S[VGREEN] + kernel.mMatrix[2][2]*SE[VGREEN]);
+            dst.mV[VBLUE] = (kernel.mMatrix[0][0]*NW[VBLUE] + kernel.mMatrix[0][1]*N[VBLUE] + kernel.mMatrix[0][2]*NE[VBLUE] +
+                             kernel.mMatrix[1][0]*W[VBLUE]  + kernel.mMatrix[1][1]*C[VBLUE] + kernel.mMatrix[1][2]*E[VBLUE] +
+                             kernel.mMatrix[2][0]*SW[VBLUE] + kernel.mMatrix[2][1]*S[VBLUE] + kernel.mMatrix[2][2]*SE[VBLUE]);
+            if (abs_value)
+            {
+                dst.mV[VRED]   = llabs(dst.mV[VRED]);
+                dst.mV[VGREEN] = llabs(dst.mV[VGREEN]);
+                dst.mV[VBLUE]  = llabs(dst.mV[VBLUE]);
+            }
+            if (normalize)
+            {
+                dst.mV[VRED]   = (dst.mV[VRED] - kernel_min)/kernel_range;
+                dst.mV[VGREEN] = (dst.mV[VGREEN] - kernel_min)/kernel_range;
+                dst.mV[VBLUE]  = (dst.mV[VBLUE] - kernel_min)/kernel_range;
+            }
+            dst.clamp(0.0f,255.0f);
+            
+            // Blend result
+            blendStencil(getStencilAlpha(i,j), dst_data, dst.mV[VRED], dst.mV[VGREEN], dst.mV[VBLUE]);
+            
+            // Next pixel
+            dst_data += components;
+            NW += components;
+            N += components;
+            NE += components;
+            W += components;
+            C += components;
+            E += components;
+            SW += components;
+            S += components;
+            SE += components;
+        }
+        // Last pixel : set to 0
+        blendStencil(getStencilAlpha(width-1,j), dst_data, 0, 0, 0);
+        dst_data += components;
+        south_data += buffer_size;
+	}
+    
+    // Last line
+    for (S32 i = 0; i < width; i++)
+    {
+        blendStencil(getStencilAlpha(i,0), dst_data, 0, 0, 0);
+        dst_data += components;
+    }
+}
+
 void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle)
 {
 	const S32 components = mImage->getComponents();
diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h
index 19ac7e81d6..738c693686 100755
--- a/indra/llimage/llimagefilter.h
+++ b/indra/llimage/llimagefilter.h
@@ -91,6 +91,7 @@ private:
     void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue);
     void filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle);
     void blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue);
+    void convolve(const LLMatrix3 &kernel, bool normalize, bool abs_value);
 
     // Procedural Stencils
     void setStencil(EStencilBlendMode mode, EStencilShape type, F32 gamma, F32 min, F32 max);
-- 
cgit v1.2.3


From 4082d8ea27a6d386a01681e51e9776b552f6cb5c Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 21 Jan 2014 16:39:23 -0800
Subject: ACME-1236 : Fixes gamma and brightness code. Also fixes example xml
 filter files.

---
 indra/integration_tests/llimage_libtest/brighten.xml |  2 +-
 indra/integration_tests/llimage_libtest/colorize.xml | 16 ++++++++++------
 indra/integration_tests/llimage_libtest/contrast.xml |  7 -------
 indra/integration_tests/llimage_libtest/darken.xml   |  2 +-
 indra/integration_tests/llimage_libtest/gamma.xml    |  9 +--------
 indra/llimage/llimagefilter.cpp                      | 13 +++++++------
 indra/llimage/llimagefilter.h                        |  2 +-
 7 files changed, 21 insertions(+), 30 deletions(-)

diff --git a/indra/integration_tests/llimage_libtest/brighten.xml b/indra/integration_tests/llimage_libtest/brighten.xml
index d17b96d2d7..9b4232229f 100755
--- a/indra/integration_tests/llimage_libtest/brighten.xml
+++ b/indra/integration_tests/llimage_libtest/brighten.xml
@@ -2,7 +2,7 @@
     <array>
         <array>
             <string>brighten</string>
-            <real>50.0</real>
+            <real>0.5</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
diff --git a/indra/integration_tests/llimage_libtest/colorize.xml b/indra/integration_tests/llimage_libtest/colorize.xml
index 18c6cd3425..72e58b0ffe 100644
--- a/indra/integration_tests/llimage_libtest/colorize.xml
+++ b/indra/integration_tests/llimage_libtest/colorize.xml
@@ -1,20 +1,24 @@
 <llsd>
     <array>
         <array>
-            <string>linearize</string>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>blend</string>
             <real>0.0</real>
             <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
             <real>1.0</real>
-            <real>1.0</real>
+            <real>10.0</real>
         </array>
         <array>
             <string>colorize</string>
             <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>0.2</real>
             <real>0.0</real>
-            <real>0.2</real>
+            <real>0.0</real>
+            <real>0.5</real>
+            <real>0.5</real>
+            <real>0.0</real>
         </array>
     </array>
 </llsd>
diff --git a/indra/integration_tests/llimage_libtest/contrast.xml b/indra/integration_tests/llimage_libtest/contrast.xml
index 8dcdd1a9a9..00746b8a9e 100644
--- a/indra/integration_tests/llimage_libtest/contrast.xml
+++ b/indra/integration_tests/llimage_libtest/contrast.xml
@@ -1,12 +1,5 @@
 <llsd>
     <array>
-        <array>
-            <string>linearize</string>
-            <real>0.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
         <array>
             <string>contrast</string>
             <real>1.5</real>
diff --git a/indra/integration_tests/llimage_libtest/darken.xml b/indra/integration_tests/llimage_libtest/darken.xml
index 8d110452e9..5cec3589b6 100755
--- a/indra/integration_tests/llimage_libtest/darken.xml
+++ b/indra/integration_tests/llimage_libtest/darken.xml
@@ -2,7 +2,7 @@
     <array>
         <array>
             <string>darken</string>
-            <real>50.0</real>
+            <real>0.5</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
diff --git a/indra/integration_tests/llimage_libtest/gamma.xml b/indra/integration_tests/llimage_libtest/gamma.xml
index 7505a03027..19af09b046 100644
--- a/indra/integration_tests/llimage_libtest/gamma.xml
+++ b/indra/integration_tests/llimage_libtest/gamma.xml
@@ -1,15 +1,8 @@
 <llsd>
     <array>
-        <array>
-            <string>linearize</string>
-            <real>0.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
         <array>
             <string>gamma</string>
-            <real>1.5</real>
+            <real>1.7</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index 75661a6d4b..c02679e04f 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -80,7 +80,6 @@ LLImageFilter::~LLImageFilter()
  * Improve perf: make sure filter is not called more than necessary in viewer (seems to be called 3 times per change)
  * Make filter definition resolution independent (do not use pixel size anywhere)
  * Add gradient coloring as a filter
- * Add convolve3x3
  
  params:
  * vignette : center_x, center_y, width, feather
@@ -251,12 +250,12 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
         else if (filter_name == "brighten")
         {
             LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
-            filterBrightness((S32)(mFilterData[i][1].asReal()),color);
+            filterBrightness((float)(mFilterData[i][1].asReal()),color);
         }
         else if (filter_name == "darken")
         {
             LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
-            filterBrightness((S32)(-mFilterData[i][1].asReal()),color);
+            filterBrightness((float)(-mFilterData[i][1].asReal()),color);
         }
         else if (filter_name == "linearize")
         {
@@ -807,7 +806,7 @@ void LLImageFilter::filterGamma(F32 gamma, const LLColor3& alpha)
     
     for (S32 i = 0; i < 256; i++)
     {
-        F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,gamma)));
+        F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,1.0/gamma)));
         // Blend in with alpha values
         gamma_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * 255.0 * gamma_i);
         gamma_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * 255.0 * gamma_i);
@@ -969,15 +968,17 @@ void LLImageFilter::filterContrast(F32 slope, const LLColor3& alpha)
     colorCorrect(contrast_red_lut,contrast_green_lut,contrast_blue_lut);
 }
 
-void LLImageFilter::filterBrightness(S32 add, const LLColor3& alpha)
+void LLImageFilter::filterBrightness(F32 add, const LLColor3& alpha)
 {
     U8 brightness_red_lut[256];
     U8 brightness_green_lut[256];
     U8 brightness_blue_lut[256];
     
+    S32 add_value = (S32)(add * 255.0);
+    
     for (S32 i = 0; i < 256; i++)
     {
-        U8 value_i = (U8)(llclampb((S32)((S32)(i) + add)));
+        U8 value_i = (U8)(llclampb(i + add_value));
         // Blend in with alpha values
         brightness_red_lut[i]   = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
         brightness_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h
index 738c693686..3e3be3d88b 100755
--- a/indra/llimage/llimagefilter.h
+++ b/indra/llimage/llimagefilter.h
@@ -84,7 +84,7 @@ private:
     void filterEqualize(S32 nb_classes, const LLColor3& alpha); // Use histogram to equalize constrast between nb_classes throughout the image
     void filterColorize(const LLColor3& color, const LLColor3& alpha);  // Colorize with color and alpha per channel
     void filterContrast(F32 slope, const LLColor3& alpha);      // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast
-    void filterBrightness(S32 add, const LLColor3& alpha);      // Change brightness according to add: > 0 brighter, < 0 darker
+    void filterBrightness(F32 add, const LLColor3& alpha);      // Change brightness according to add: > 0 brighter, < 0 darker
     
     // Filter Primitives
     void colorTransform(const LLMatrix3 &transform);
-- 
cgit v1.2.3


From c99e22e6740ebb3e39bc1b85000bd465676e60d1 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 21 Jan 2014 21:17:57 -0800
Subject: ACME-1236 : Make all filters resolution independent, cleanup
 comments, move example filters to a sub folder in llimage_libtest

---
 .../llimage_libtest/1970colorize.xml               | 41 -------------
 indra/integration_tests/llimage_libtest/blur.xml   |  7 ---
 .../integration_tests/llimage_libtest/brighten.xml | 11 ----
 .../integration_tests/llimage_libtest/colorize.xml | 24 --------
 .../integration_tests/llimage_libtest/contrast.xml | 11 ----
 indra/integration_tests/llimage_libtest/darken.xml | 11 ----
 indra/integration_tests/llimage_libtest/edges.xml  | 24 --------
 .../llimage_libtest/filters/1970colorize.xml       | 41 +++++++++++++
 .../llimage_libtest/filters/blur.xml               |  7 +++
 .../llimage_libtest/filters/brighten.xml           | 11 ++++
 .../llimage_libtest/filters/colorize.xml           | 24 ++++++++
 .../llimage_libtest/filters/contrast.xml           | 11 ++++
 .../llimage_libtest/filters/darken.xml             | 11 ++++
 .../llimage_libtest/filters/edges.xml              | 24 ++++++++
 .../llimage_libtest/filters/gamma.xml              | 11 ++++
 .../llimage_libtest/filters/grayscale.xml          | 14 +++++
 .../llimage_libtest/filters/horizontalscreen.xml   | 20 +++++++
 .../llimage_libtest/filters/linearize.xml          | 11 ++++
 .../llimage_libtest/filters/newsscreen.xml         | 20 +++++++
 .../llimage_libtest/filters/posterize.xml          | 11 ++++
 .../llimage_libtest/filters/rotatecolors180.xml    |  8 +++
 .../llimage_libtest/filters/saturate.xml           |  8 +++
 .../llimage_libtest/filters/sepia.xml              | 14 +++++
 .../llimage_libtest/filters/sharpen.xml            |  7 +++
 .../llimage_libtest/filters/slantedscreen.xml      | 20 +++++++
 .../llimage_libtest/filters/spotlight.xml          | 45 ++++++++++++++
 .../llimage_libtest/filters/stencilgradient.xml    | 24 ++++++++
 .../llimage_libtest/filters/stencilscanlines.xml   | 22 +++++++
 .../llimage_libtest/filters/stenciluniform.xml     | 20 +++++++
 .../llimage_libtest/filters/stencilvignette.xml    | 24 ++++++++
 .../llimage_libtest/filters/verticalscreen.xml     | 20 +++++++
 .../llimage_libtest/filters/video.xml              | 23 +++++++
 indra/integration_tests/llimage_libtest/gamma.xml  | 11 ----
 .../llimage_libtest/grayscale.xml                  | 14 -----
 .../llimage_libtest/horizontalscreen.xml           | 25 --------
 .../llimage_libtest/linearize.xml                  | 11 ----
 .../llimage_libtest/newsscreen.xml                 | 25 --------
 .../llimage_libtest/posterize.xml                  | 18 ------
 .../llimage_libtest/rotatecolors180.xml            |  8 ---
 .../integration_tests/llimage_libtest/saturate.xml |  8 ---
 indra/integration_tests/llimage_libtest/sepia.xml  | 14 -----
 .../integration_tests/llimage_libtest/sharpen.xml  |  7 ---
 .../llimage_libtest/slantedscreen.xml              | 25 --------
 .../llimage_libtest/spotlight.xml                  | 45 --------------
 .../llimage_libtest/verticalscreen.xml             | 25 --------
 indra/integration_tests/llimage_libtest/video.xml  | 23 -------
 indra/llimage/llimagefilter.cpp                    | 70 ++++------------------
 indra/llimage/llimagefilter.h                      |  4 +-
 48 files changed, 464 insertions(+), 449 deletions(-)
 delete mode 100644 indra/integration_tests/llimage_libtest/1970colorize.xml
 delete mode 100644 indra/integration_tests/llimage_libtest/blur.xml
 delete mode 100755 indra/integration_tests/llimage_libtest/brighten.xml
 delete mode 100644 indra/integration_tests/llimage_libtest/colorize.xml
 delete mode 100644 indra/integration_tests/llimage_libtest/contrast.xml
 delete mode 100755 indra/integration_tests/llimage_libtest/darken.xml
 delete mode 100644 indra/integration_tests/llimage_libtest/edges.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/1970colorize.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/blur.xml
 create mode 100755 indra/integration_tests/llimage_libtest/filters/brighten.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/colorize.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/contrast.xml
 create mode 100755 indra/integration_tests/llimage_libtest/filters/darken.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/edges.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/gamma.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/grayscale.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/horizontalscreen.xml
 create mode 100755 indra/integration_tests/llimage_libtest/filters/linearize.xml
 create mode 100755 indra/integration_tests/llimage_libtest/filters/newsscreen.xml
 create mode 100755 indra/integration_tests/llimage_libtest/filters/posterize.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/rotatecolors180.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/saturate.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/sepia.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/sharpen.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/slantedscreen.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/spotlight.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/stencilgradient.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/stencilscanlines.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/stenciluniform.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/stencilvignette.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/verticalscreen.xml
 create mode 100755 indra/integration_tests/llimage_libtest/filters/video.xml
 delete mode 100644 indra/integration_tests/llimage_libtest/gamma.xml
 delete mode 100644 indra/integration_tests/llimage_libtest/grayscale.xml
 delete mode 100644 indra/integration_tests/llimage_libtest/horizontalscreen.xml
 delete mode 100755 indra/integration_tests/llimage_libtest/linearize.xml
 delete mode 100755 indra/integration_tests/llimage_libtest/newsscreen.xml
 delete mode 100755 indra/integration_tests/llimage_libtest/posterize.xml
 delete mode 100644 indra/integration_tests/llimage_libtest/rotatecolors180.xml
 delete mode 100644 indra/integration_tests/llimage_libtest/saturate.xml
 delete mode 100644 indra/integration_tests/llimage_libtest/sepia.xml
 delete mode 100644 indra/integration_tests/llimage_libtest/sharpen.xml
 delete mode 100644 indra/integration_tests/llimage_libtest/slantedscreen.xml
 delete mode 100644 indra/integration_tests/llimage_libtest/spotlight.xml
 delete mode 100644 indra/integration_tests/llimage_libtest/verticalscreen.xml
 delete mode 100755 indra/integration_tests/llimage_libtest/video.xml

diff --git a/indra/integration_tests/llimage_libtest/1970colorize.xml b/indra/integration_tests/llimage_libtest/1970colorize.xml
deleted file mode 100644
index 0dab2489a0..0000000000
--- a/indra/integration_tests/llimage_libtest/1970colorize.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>contrast</string>
-            <real>0.8</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>colorize</string>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>0.5</real>
-            <real>0.0</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>blend</string>
-            <real>10.0</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>colorize</string>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>0.1</real>
-            <real>0.1</real>
-            <real>0.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/blur.xml b/indra/integration_tests/llimage_libtest/blur.xml
deleted file mode 100644
index addd056855..0000000000
--- a/indra/integration_tests/llimage_libtest/blur.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>blur</string>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/brighten.xml b/indra/integration_tests/llimage_libtest/brighten.xml
deleted file mode 100755
index 9b4232229f..0000000000
--- a/indra/integration_tests/llimage_libtest/brighten.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>brighten</string>
-            <real>0.5</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/colorize.xml b/indra/integration_tests/llimage_libtest/colorize.xml
deleted file mode 100644
index 72e58b0ffe..0000000000
--- a/indra/integration_tests/llimage_libtest/colorize.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>stencil</string>
-            <string>vignette</string>
-            <string>blend</string>
-            <real>0.0</real>
-            <real>1.0</real>
-            <real>0.0</real>
-            <real>0.0</real>
-            <real>1.0</real>
-            <real>10.0</real>
-        </array>
-        <array>
-            <string>colorize</string>
-            <real>1.0</real>
-            <real>0.0</real>
-            <real>0.0</real>
-            <real>0.5</real>
-            <real>0.5</real>
-            <real>0.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/contrast.xml b/indra/integration_tests/llimage_libtest/contrast.xml
deleted file mode 100644
index 00746b8a9e..0000000000
--- a/indra/integration_tests/llimage_libtest/contrast.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>contrast</string>
-            <real>1.5</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/darken.xml b/indra/integration_tests/llimage_libtest/darken.xml
deleted file mode 100755
index 5cec3589b6..0000000000
--- a/indra/integration_tests/llimage_libtest/darken.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>darken</string>
-            <real>0.5</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/edges.xml b/indra/integration_tests/llimage_libtest/edges.xml
deleted file mode 100644
index a66b81d01e..0000000000
--- a/indra/integration_tests/llimage_libtest/edges.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>gradient</string>
-        </array>
-        <array>
-            <string>blur</string>
-        </array>
-        <array>
-            <string>linearize</string>
-            <real>0.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>contrast</string>
-            <real>2.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/1970colorize.xml b/indra/integration_tests/llimage_libtest/filters/1970colorize.xml
new file mode 100644
index 0000000000..0dab2489a0
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/1970colorize.xml
@@ -0,0 +1,41 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.5</real>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>blend</string>
+            <real>10.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.1</real>
+            <real>0.1</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/blur.xml b/indra/integration_tests/llimage_libtest/filters/blur.xml
new file mode 100644
index 0000000000..addd056855
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/blur.xml
@@ -0,0 +1,7 @@
+<llsd>
+    <array>
+        <array>
+            <string>blur</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/brighten.xml b/indra/integration_tests/llimage_libtest/filters/brighten.xml
new file mode 100755
index 0000000000..9b4232229f
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/brighten.xml
@@ -0,0 +1,11 @@
+<llsd>
+    <array>
+        <array>
+            <string>brighten</string>
+            <real>0.5</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/colorize.xml b/indra/integration_tests/llimage_libtest/filters/colorize.xml
new file mode 100644
index 0000000000..72e58b0ffe
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/colorize.xml
@@ -0,0 +1,24 @@
+<llsd>
+    <array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>blend</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>10.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>0.5</real>
+            <real>0.5</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/contrast.xml b/indra/integration_tests/llimage_libtest/filters/contrast.xml
new file mode 100644
index 0000000000..00746b8a9e
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/contrast.xml
@@ -0,0 +1,11 @@
+<llsd>
+    <array>
+        <array>
+            <string>contrast</string>
+            <real>1.5</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/darken.xml b/indra/integration_tests/llimage_libtest/filters/darken.xml
new file mode 100755
index 0000000000..5cec3589b6
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/darken.xml
@@ -0,0 +1,11 @@
+<llsd>
+    <array>
+        <array>
+            <string>darken</string>
+            <real>0.5</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/edges.xml b/indra/integration_tests/llimage_libtest/filters/edges.xml
new file mode 100644
index 0000000000..a66b81d01e
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/edges.xml
@@ -0,0 +1,24 @@
+<llsd>
+    <array>
+        <array>
+            <string>gradient</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>2.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/gamma.xml b/indra/integration_tests/llimage_libtest/filters/gamma.xml
new file mode 100644
index 0000000000..19af09b046
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/gamma.xml
@@ -0,0 +1,11 @@
+<llsd>
+    <array>
+        <array>
+            <string>gamma</string>
+            <real>1.7</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/grayscale.xml b/indra/integration_tests/llimage_libtest/filters/grayscale.xml
new file mode 100644
index 0000000000..984312c4fd
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/grayscale.xml
@@ -0,0 +1,14 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/horizontalscreen.xml b/indra/integration_tests/llimage_libtest/filters/horizontalscreen.xml
new file mode 100644
index 0000000000..21cab70e54
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/horizontalscreen.xml
@@ -0,0 +1,20 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+        <array>
+            <string>screen</string>
+            <string>line</string>
+            <real>0.015</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/linearize.xml b/indra/integration_tests/llimage_libtest/filters/linearize.xml
new file mode 100755
index 0000000000..23d0290e07
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/linearize.xml
@@ -0,0 +1,11 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/newsscreen.xml b/indra/integration_tests/llimage_libtest/filters/newsscreen.xml
new file mode 100755
index 0000000000..50ed27c6db
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/newsscreen.xml
@@ -0,0 +1,20 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+        <array>
+            <string>screen</string>
+            <string>2Dsine</string>
+            <real>0.015</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/posterize.xml b/indra/integration_tests/llimage_libtest/filters/posterize.xml
new file mode 100755
index 0000000000..4d03df3c66
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/posterize.xml
@@ -0,0 +1,11 @@
+<llsd>
+    <array>
+        <array>
+            <string>posterize</string>
+            <real>10.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/rotatecolors180.xml b/indra/integration_tests/llimage_libtest/filters/rotatecolors180.xml
new file mode 100644
index 0000000000..e25029720f
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/rotatecolors180.xml
@@ -0,0 +1,8 @@
+<llsd>
+    <array>
+        <array>
+            <string>rotate</string>
+            <real>180.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/saturate.xml b/indra/integration_tests/llimage_libtest/filters/saturate.xml
new file mode 100644
index 0000000000..b77f07a037
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/saturate.xml
@@ -0,0 +1,8 @@
+<llsd>
+    <array>
+        <array>
+            <string>saturate</string>
+            <real>3.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/sepia.xml b/indra/integration_tests/llimage_libtest/filters/sepia.xml
new file mode 100644
index 0000000000..0304ead015
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/sepia.xml
@@ -0,0 +1,14 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>sepia</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/sharpen.xml b/indra/integration_tests/llimage_libtest/filters/sharpen.xml
new file mode 100644
index 0000000000..6d3f9ae1a2
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/sharpen.xml
@@ -0,0 +1,7 @@
+<llsd>
+    <array>
+        <array>
+            <string>sharpen</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/slantedscreen.xml b/indra/integration_tests/llimage_libtest/filters/slantedscreen.xml
new file mode 100644
index 0000000000..6cd1a96185
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/slantedscreen.xml
@@ -0,0 +1,20 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+        <array>
+            <string>screen</string>
+            <string>line</string>
+            <real>0.015</real>
+            <real>45.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/spotlight.xml b/indra/integration_tests/llimage_libtest/filters/spotlight.xml
new file mode 100644
index 0000000000..203130bdee
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/spotlight.xml
@@ -0,0 +1,45 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>saturate</string>
+            <real>1.5</real>
+        </array>
+        <array>
+            <string>fade</string>
+            <real>1.0</real>
+            <real>0.25</real>
+        </array>
+        <array>
+            <string>saturate</string>
+            <real>0.8</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>1.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>brighten</string>
+            <real>30</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/stencilgradient.xml b/indra/integration_tests/llimage_libtest/filters/stencilgradient.xml
new file mode 100644
index 0000000000..d22809a9bf
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/stencilgradient.xml
@@ -0,0 +1,24 @@
+<llsd>
+    <array>
+        <array>
+            <string>stencil</string>
+            <string>gradient</string>
+            <string>blend</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>-1.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/stencilscanlines.xml b/indra/integration_tests/llimage_libtest/filters/stencilscanlines.xml
new file mode 100644
index 0000000000..3ce428503d
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/stencilscanlines.xml
@@ -0,0 +1,22 @@
+<llsd>
+    <array>
+        <array>
+            <string>stencil</string>
+            <string>scanlines</string>
+            <string>blend</string>
+            <real>0.0</real>
+            <real>0.5</real>
+            <real>0.1</real>
+            <real>45.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/stenciluniform.xml b/indra/integration_tests/llimage_libtest/filters/stenciluniform.xml
new file mode 100644
index 0000000000..7d72f0ed93
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/stenciluniform.xml
@@ -0,0 +1,20 @@
+<llsd>
+    <array>
+        <array>
+            <string>stencil</string>
+            <string>uniform</string>
+            <string>blend</string>
+            <real>0.0</real>
+            <real>0.5</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/stencilvignette.xml b/indra/integration_tests/llimage_libtest/filters/stencilvignette.xml
new file mode 100644
index 0000000000..d30637fef5
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/stencilvignette.xml
@@ -0,0 +1,24 @@
+<llsd>
+    <array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>blend</string>
+            <real>0.0</real>
+            <real>0.5</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>10.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/verticalscreen.xml b/indra/integration_tests/llimage_libtest/filters/verticalscreen.xml
new file mode 100644
index 0000000000..0768d1d7e1
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/verticalscreen.xml
@@ -0,0 +1,20 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+        <array>
+            <string>screen</string>
+            <string>line</string>
+            <real>0.015</real>
+            <real>90.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/video.xml b/indra/integration_tests/llimage_libtest/filters/video.xml
new file mode 100755
index 0000000000..8b10687ef5
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/video.xml
@@ -0,0 +1,23 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.01</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>lines</string>
+            <real>10.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>brighten</string>
+            <real>100.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/gamma.xml b/indra/integration_tests/llimage_libtest/gamma.xml
deleted file mode 100644
index 19af09b046..0000000000
--- a/indra/integration_tests/llimage_libtest/gamma.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>gamma</string>
-            <real>1.7</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/grayscale.xml b/indra/integration_tests/llimage_libtest/grayscale.xml
deleted file mode 100644
index 984312c4fd..0000000000
--- a/indra/integration_tests/llimage_libtest/grayscale.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>grayscale</string>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/horizontalscreen.xml b/indra/integration_tests/llimage_libtest/horizontalscreen.xml
deleted file mode 100644
index ddff4d1977..0000000000
--- a/indra/integration_tests/llimage_libtest/horizontalscreen.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>grayscale</string>
-        </array>
-        <array>
-            <string>blend</string>
-            <real>0.0</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>screen</string>
-            <string>line</string>
-            <real>5.0</real>
-            <real>0.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/linearize.xml b/indra/integration_tests/llimage_libtest/linearize.xml
deleted file mode 100755
index 23d0290e07..0000000000
--- a/indra/integration_tests/llimage_libtest/linearize.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/newsscreen.xml b/indra/integration_tests/llimage_libtest/newsscreen.xml
deleted file mode 100755
index 8247c34500..0000000000
--- a/indra/integration_tests/llimage_libtest/newsscreen.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>grayscale</string>
-        </array>
-        <array>
-            <string>blend</string>
-            <real>0.0</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>screen</string>
-            <string>2Dsine</string>
-            <real>5.0</real>
-            <real>0.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/posterize.xml b/indra/integration_tests/llimage_libtest/posterize.xml
deleted file mode 100755
index f026278f9e..0000000000
--- a/indra/integration_tests/llimage_libtest/posterize.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>posterize</string>
-            <real>10.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/rotatecolors180.xml b/indra/integration_tests/llimage_libtest/rotatecolors180.xml
deleted file mode 100644
index e25029720f..0000000000
--- a/indra/integration_tests/llimage_libtest/rotatecolors180.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>rotate</string>
-            <real>180.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/saturate.xml b/indra/integration_tests/llimage_libtest/saturate.xml
deleted file mode 100644
index b77f07a037..0000000000
--- a/indra/integration_tests/llimage_libtest/saturate.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>saturate</string>
-            <real>3.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/sepia.xml b/indra/integration_tests/llimage_libtest/sepia.xml
deleted file mode 100644
index 0304ead015..0000000000
--- a/indra/integration_tests/llimage_libtest/sepia.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>sepia</string>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/sharpen.xml b/indra/integration_tests/llimage_libtest/sharpen.xml
deleted file mode 100644
index 6d3f9ae1a2..0000000000
--- a/indra/integration_tests/llimage_libtest/sharpen.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>sharpen</string>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/slantedscreen.xml b/indra/integration_tests/llimage_libtest/slantedscreen.xml
deleted file mode 100644
index 63ad01d51d..0000000000
--- a/indra/integration_tests/llimage_libtest/slantedscreen.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>grayscale</string>
-        </array>
-        <array>
-            <string>blend</string>
-            <real>0.0</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>screen</string>
-            <string>line</string>
-            <real>5.0</real>
-            <real>45.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/spotlight.xml b/indra/integration_tests/llimage_libtest/spotlight.xml
deleted file mode 100644
index 203130bdee..0000000000
--- a/indra/integration_tests/llimage_libtest/spotlight.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>contrast</string>
-            <real>0.8</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>saturate</string>
-            <real>1.5</real>
-        </array>
-        <array>
-            <string>fade</string>
-            <real>1.0</real>
-            <real>0.25</real>
-        </array>
-        <array>
-            <string>saturate</string>
-            <real>0.8</real>
-        </array>
-        <array>
-            <string>contrast</string>
-            <real>1.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>brighten</string>
-            <real>30</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/verticalscreen.xml b/indra/integration_tests/llimage_libtest/verticalscreen.xml
deleted file mode 100644
index 71e48df656..0000000000
--- a/indra/integration_tests/llimage_libtest/verticalscreen.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>grayscale</string>
-        </array>
-        <array>
-            <string>blend</string>
-            <real>0.0</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>screen</string>
-            <string>line</string>
-            <real>5.0</real>
-            <real>90.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/integration_tests/llimage_libtest/video.xml b/indra/integration_tests/llimage_libtest/video.xml
deleted file mode 100755
index 8b10687ef5..0000000000
--- a/indra/integration_tests/llimage_libtest/video.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.01</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>lines</string>
-            <real>10.0</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>brighten</string>
-            <real>100.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index c02679e04f..4c6dd2faee 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -1,6 +1,6 @@
 /** 
  * @file llimagefilter.cpp
- * @brief Simple Image Filtering.
+ * @brief Simple Image Filtering. See https://wiki.lindenlab.com/wiki/SL_Viewer_Image_Filters for complete documentation.
  *
  * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -75,42 +75,12 @@ LLImageFilter::~LLImageFilter()
 
 /*
  *TODO 
- * Test blend modes
+ * Rename stencil to mask
+ * Test blend modes and name them correctly
+ * Suppress old "blend", "fade" and "lines" stencil definition. Change all xml accordingly.
  * Improve perf: use LUT for alpha blending in uniform case
  * Improve perf: make sure filter is not called more than necessary in viewer (seems to be called 3 times per change)
- * Make filter definition resolution independent (do not use pixel size anywhere)
  * Add gradient coloring as a filter
- 
- params:
- * vignette : center_x, center_y, width, feather
- * scan lines : wavelength, angle
- * uniform
- * gradient : start_x, start_y, end_x, end_y
-
- * Document all the admissible names in the wiki
- 
- "        Apply the filter <name> to the input images using the optional <param> value. Admissible names:\n"
- "        - 'grayscale' converts to grayscale (no param).\n"
- "        - 'sepia' converts to sepia (no param).\n"
- "        - 'saturate' changes color saturation according to <param>: < 1.0 will desaturate, > 1.0 will saturate.\n"
- "        - 'rotate' rotates the color hue according to <param> (in degree, positive value only).\n"
- 
- "        - 'gamma' applies a gamma curve <param> to all channels: > 1.0 will darken, < 1.0 will lighten.\n"
- "        - 'colorize' applies a colored tint <param1, param2, param3> to the image.\n"
- "        - 'contrast' modifies the contrast according to <param> : > 1.0 will enhance the contrast, <1.0 will flatten it.\n"
- "        - 'brighten' adds <param> light to the image (<param> between 0 and 255).\n"
- "        - 'darken' substracts <param> light to the image (<param> between 0 and 255).\n"
- "        - 'linearize' optimizes the contrast using the brightness histogram. <param> is the fraction (between 0.0 and 1.0) of the discarded head and tail of the histogram.\n"
- "        - 'posterize' redistributes the colors between <param> classes per channel (<param> between 2 and 255).\n"
- 
- "        - 'screen' applies a screening filter to the red channel and output to black and white. This filter assumes that the input image has been converted to grayscale or that the red channel is somewhat meaningful. It takes 3 parameters: a mode, a wave length and an angle. Modes are:\n"
- "            - '2Dsine' applies a bidirectional (x,y) sine screen. <angle> has no influence on that mode.\n"
- "            - 'line' applies a linear sine screen. <angle> is the line generator angle with the horizontal.\n"
- "         <wave_length> is size between 2 peaks of the sine function in normalized image coordinates."
-
- "        Apply a circular central vignette <name> to the filter using the optional <feather> and <min> values. Admissible names:\n"
- "        - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n"
- "        - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n"
  */
 
 //============================================================================
@@ -133,25 +103,6 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
         //}
         //std::cout << std::endl;
         
-        // Execute the filter described on this line
-        /*
-        <array>
-        <string>stencil</string> 
-        <string>shape</string> uniform / gradient / vignette / scanlines
-        <string>blend_mode</string> blend /add /dodge / fade
-        <real>min</real> -1.0 to 1.0 (mandatory though ignored for uniform shape)
-        <real>max</real> -1.0 to 1.0 (value for uniform)
-        <real>param1</real>
-        <real>param2</real>
-        <real>param3</real>
-        <real>param4</real>
-        </array>
-         params:
-         * vignette : center_x, center_y, width, feather : positions between in float (0.0 is center, 1.0 is top), width in float in same unit, feather is a float
-         * scan lines : wavelength, angle : wavelength in float assuming (height/2 = 1), angle float in degree
-         * uniform : all parameters ignored
-         * gradient : start_x, start_y, end_x, end_y : position in float (0.0 is center, 1.0 is top)
-         */
         if (filter_name == "stencil")
         {
             // Get the shape of the stencil, that is how the procedural alpha is computed geometrically
@@ -279,7 +230,7 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
             {
                 mode = SCREEN_MODE_LINE;
             }
-            filterScreen(mode,(S32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal()));
+            filterScreen(mode,(F32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal()));
         }
         else if (filter_name == "blur")
         {
@@ -445,7 +396,7 @@ void LLImageFilter::convolve(const LLMatrix3 &kernel, bool normalize, bool abs_v
     // All other lines
     for (S32 j = 1; j < (height-1); j++)
 	{
-        // We need to buffer 2 lines. We flip north and current to avoid moving too much memory around
+        // We need to buffer 2 lines. We flip north and east-west (current) to avoid moving too much memory around
         if (j % 2)
         {
             memcpy( &odd_buffer[0], dst_data, buffer_size );	/* Flawfinder: ignore */
@@ -460,6 +411,7 @@ void LLImageFilter::convolve(const LLMatrix3 &kernel, bool normalize, bool abs_v
         }
         // First pixel : set to 0
         blendStencil(getStencilAlpha(0,j), dst_data, 0, 0, 0);
+        dst_data += components;
         // Set pointers to kernel
         U8* NW = north_data;
         U8* N = NW+components;
@@ -470,7 +422,6 @@ void LLImageFilter::convolve(const LLMatrix3 &kernel, bool normalize, bool abs_v
         U8* SW = south_data;
         U8* S = SW+components;
         U8* SE = S+components;
-        dst_data += components;
         // All other pixels
         for (S32 i = 1; i < (width-1); i++)
         {
@@ -528,7 +479,7 @@ void LLImageFilter::convolve(const LLMatrix3 &kernel, bool normalize, bool abs_v
     }
 }
 
-void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle)
+void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const F32 angle)
 {
 	const S32 components = mImage->getComponents();
 	llassert( components >= 1 && components <= 4 );
@@ -536,6 +487,7 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const
 	S32 width  = mImage->getWidth();
     S32 height = mImage->getHeight();
     
+    F32 wave_length_pixels = wave_length * (F32)(height) / 2.0;
     F32 sin = sinf(angle*DEG_TO_RAD);
     F32 cos = cosf(angle*DEG_TO_RAD);
     
@@ -550,11 +502,11 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const
             switch (mode)
             {
                 case SCREEN_MODE_2DSINE:
-                    value = (sinf(2*F_PI*i/wave_length)*sinf(2*F_PI*j/wave_length)+1.0)*255.0/2.0;
+                    value = (sinf(2*F_PI*i/wave_length_pixels)*sinf(2*F_PI*j/wave_length_pixels)+1.0)*255.0/2.0;
                     break;
                 case SCREEN_MODE_LINE:
                     d = sin*i - cos*j;
-                    value = (sinf(2*F_PI*d/wave_length)+1.0)*255.0/2.0;
+                    value = (sinf(2*F_PI*d/wave_length_pixels)+1.0)*255.0/2.0;
                     break;
             }
             U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0);
diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h
index 3e3be3d88b..e392d3215e 100755
--- a/indra/llimage/llimagefilter.h
+++ b/indra/llimage/llimagefilter.h
@@ -1,6 +1,6 @@
 /** 
  * @file llimagefilter.h
- * @brief Simple Image Filtering.
+ * @brief Simple Image Filtering. See https://wiki.lindenlab.com/wiki/SL_Viewer_Image_Filters for complete documentation.
  *
  * $LicenseInfo:firstyear=2000&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -89,7 +89,7 @@ private:
     // Filter Primitives
     void colorTransform(const LLMatrix3 &transform);
     void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue);
-    void filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle);
+    void filterScreen(EScreenMode mode, const F32 wave_length, const F32 angle);
     void blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue);
     void convolve(const LLMatrix3 &kernel, bool normalize, bool abs_value);
 
-- 
cgit v1.2.3


From 88b65f32c7c09264e801178e75975db28d42a54c Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 21 Jan 2014 22:16:39 -0800
Subject: ACME-1236 : Modifies the 10 shipped filters to use the new stencils
 and resolution independent filters

---
 indra/newview/app_settings/filters/Colors1970.xml | 10 ++++++++--
 indra/newview/app_settings/filters/Heatwave.xml   |  8 +++++++-
 indra/newview/app_settings/filters/JulesVerne.xml |  8 +++++++-
 indra/newview/app_settings/filters/Newspaper.xml  |  8 +++++++-
 indra/newview/app_settings/filters/Sepia.xml      |  8 +++++++-
 indra/newview/app_settings/filters/Spotlight.xml  | 10 ++++++++--
 indra/newview/app_settings/filters/Video.xml      | 12 ++++++++----
 7 files changed, 52 insertions(+), 12 deletions(-)

diff --git a/indra/newview/app_settings/filters/Colors1970.xml b/indra/newview/app_settings/filters/Colors1970.xml
index 0dab2489a0..730d907fa7 100644
--- a/indra/newview/app_settings/filters/Colors1970.xml
+++ b/indra/newview/app_settings/filters/Colors1970.xml
@@ -19,14 +19,20 @@
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
-            <real>0.5</real>
+            <real>0.3</real>
             <real>0.0</real>
             <real>0.0</real>
         </array>
         <array>
+            <string>stencil</string>
+            <string>vignette</string>
             <string>blend</string>
-            <real>10.0</real>
             <real>0.0</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>10.0</real>
         </array>
         <array>
             <string>colorize</string>
diff --git a/indra/newview/app_settings/filters/Heatwave.xml b/indra/newview/app_settings/filters/Heatwave.xml
index 5c47ca0f84..a99f41c833 100644
--- a/indra/newview/app_settings/filters/Heatwave.xml
+++ b/indra/newview/app_settings/filters/Heatwave.xml
@@ -15,9 +15,15 @@
             <real>1.0</real>
         </array>
         <array>
+            <string>stencil</string>
+            <string>vignette</string>
             <string>fade</string>
-            <real>4.0</real>
             <real>0.5</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>4.0</real>
         </array>
         <array>
             <string>colorize</string>
diff --git a/indra/newview/app_settings/filters/JulesVerne.xml b/indra/newview/app_settings/filters/JulesVerne.xml
index ddff4d1977..b0d4f8e9cd 100644
--- a/indra/newview/app_settings/filters/JulesVerne.xml
+++ b/indra/newview/app_settings/filters/JulesVerne.xml
@@ -11,14 +11,20 @@
             <string>grayscale</string>
         </array>
         <array>
+            <string>stencil</string>
+            <string>vignette</string>
             <string>blend</string>
             <real>0.0</real>
+            <real>1.0</real>
+            <real>0.0</real>
             <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
         </array>
         <array>
             <string>screen</string>
             <string>line</string>
-            <real>5.0</real>
+            <real>0.01</real>
             <real>0.0</real>
         </array>
     </array>
diff --git a/indra/newview/app_settings/filters/Newspaper.xml b/indra/newview/app_settings/filters/Newspaper.xml
index 8247c34500..b02a553dfa 100755
--- a/indra/newview/app_settings/filters/Newspaper.xml
+++ b/indra/newview/app_settings/filters/Newspaper.xml
@@ -11,14 +11,20 @@
             <string>grayscale</string>
         </array>
         <array>
+            <string>stencil</string>
+            <string>vignette</string>
             <string>blend</string>
             <real>0.0</real>
+            <real>1.0</real>
+            <real>0.0</real>
             <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
         </array>
         <array>
             <string>screen</string>
             <string>2Dsine</string>
-            <real>5.0</real>
+            <real>0.01</real>
             <real>0.0</real>
         </array>
     </array>
diff --git a/indra/newview/app_settings/filters/Sepia.xml b/indra/newview/app_settings/filters/Sepia.xml
index d26df608b9..3d577b2998 100644
--- a/indra/newview/app_settings/filters/Sepia.xml
+++ b/indra/newview/app_settings/filters/Sepia.xml
@@ -15,9 +15,15 @@
             <real>1.0</real>
         </array>
         <array>
+            <string>stencil</string>
+            <string>vignette</string>
             <string>fade</string>
-            <real>4.0</real>
             <real>0.5</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>4.0</real>
         </array>
         <array>
             <string>sepia</string>
diff --git a/indra/newview/app_settings/filters/Spotlight.xml b/indra/newview/app_settings/filters/Spotlight.xml
index 203130bdee..044b2c0b3a 100644
--- a/indra/newview/app_settings/filters/Spotlight.xml
+++ b/indra/newview/app_settings/filters/Spotlight.xml
@@ -19,9 +19,15 @@
             <real>1.5</real>
         </array>
         <array>
+            <string>stencil</string>
+            <string>vignette</string>
             <string>fade</string>
+            <real>0.75</real>
             <real>1.0</real>
-            <real>0.25</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>5.0</real>
         </array>
         <array>
             <string>saturate</string>
@@ -36,7 +42,7 @@
         </array>
         <array>
             <string>brighten</string>
-            <real>30</real>
+            <real>0.1</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
diff --git a/indra/newview/app_settings/filters/Video.xml b/indra/newview/app_settings/filters/Video.xml
index 144f340f12..09c4c79638 100755
--- a/indra/newview/app_settings/filters/Video.xml
+++ b/indra/newview/app_settings/filters/Video.xml
@@ -9,19 +9,23 @@
         </array>
         <array>
             <string>darken</string>
-            <real>15.0</real>
+            <real>0.1</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
         </array>
         <array>
-            <string>lines</string>
-            <real>10.0</real>
+            <string>stencil</string>
+            <string>scanlines</string>
+            <string>blend</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>0.01</real>
             <real>0.0</real>
         </array>
         <array>
             <string>brighten</string>
-            <real>30.0</real>
+            <real>0.1</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
-- 
cgit v1.2.3


From ff3edd06d2c824a32753e689de3369abf593c684 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Thu, 23 Jan 2014 16:37:48 -0800
Subject: ACME-1275 : WIP : Clean up unwanted code and comments in image filter

---
 indra/llimage/llimagefilter.cpp | 17 ++++-------------
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index 4c6dd2faee..e0dae9fab2 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -77,7 +77,6 @@ LLImageFilter::~LLImageFilter()
  *TODO 
  * Rename stencil to mask
  * Test blend modes and name them correctly
- * Suppress old "blend", "fade" and "lines" stencil definition. Change all xml accordingly.
  * Improve perf: use LUT for alpha blending in uniform case
  * Improve perf: make sure filter is not called more than necessary in viewer (seems to be called 3 times per change)
  * Add gradient coloring as a filter
@@ -154,18 +153,6 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
             // Set the stencil
             setStencil(shape,mode,min,max,params);
         }
-        else if (filter_name == "blend")
-        {
-            setStencil(STENCIL_BLEND_MODE_BLEND,STENCIL_SHAPE_VIGNETTE,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0);
-        }
-        else if (filter_name == "fade")
-        {
-            setStencil(STENCIL_BLEND_MODE_FADE,STENCIL_SHAPE_VIGNETTE,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0);
-        }
-        else if (filter_name == "lines")
-        {
-            setStencil(STENCIL_BLEND_MODE_BLEND,STENCIL_SHAPE_SCAN_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0);
-        }
         else if (filter_name == "sepia")
         {
             filterSepia();
@@ -258,6 +245,10 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
             kernel.mMatrix[1][1] = 8.0;
             convolve(kernel,false,true);
         }
+        else
+        {
+            llwarns << "Filter unknown, cannot execute filter command : " << filter_name << llendl;
+        }
     }
 }
 
-- 
cgit v1.2.3


From 6bf3cb875cef4da7c35850ebbea5100dc5244601 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 28 Jan 2014 10:19:57 -0800
Subject: ACME-1195 : WIP : Lazy evaluate intermediate images in snapshot
 preview so perf is better in common cases, allow thumbnail to be computed
 from grabed frame (for SL Share), thumbnail display still buggy in SL Share

---
 indra/llimage/llimage.cpp               |  80 +++---
 indra/llimage/llimage.h                 |   3 +
 indra/newview/llfloaterfacebook.cpp     |   3 +-
 indra/newview/llfloaterflickr.cpp       |   4 +-
 indra/newview/llfloatersnapshot.cpp     |   5 +-
 indra/newview/llfloatertwitter.cpp      |   6 +-
 indra/newview/llsnapshotlivepreview.cpp | 443 +++++++++++++++++++-------------
 indra/newview/llsnapshotlivepreview.h   |  14 +-
 8 files changed, 318 insertions(+), 240 deletions(-)

diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index c8a05e1fae..18e08b94a6 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -449,18 +449,8 @@ void LLImageRaw::verticalFlip()
 void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image)
 {
 	// Find new sizes
-	S32 new_width = MIN_IMAGE_SIZE;
-	S32 new_height = MIN_IMAGE_SIZE;
-
-	while( (new_width < getWidth()) && (new_width < max_dim) )
-	{
-		new_width <<= 1;
-	}
-
-	while( (new_height < getHeight()) && (new_height < max_dim) )
-	{
-		new_height <<= 1;
-	}
+	S32 new_width  = expandDimToPowerOfTwo(getWidth(), max_dim);
+	S32 new_height = expandDimToPowerOfTwo(getHeight(), max_dim);
 
 	scale( new_width, new_height, scale_image );
 }
@@ -468,55 +458,61 @@ void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image)
 void LLImageRaw::contractToPowerOfTwo(S32 max_dim, BOOL scale_image)
 {
 	// Find new sizes
-	S32 new_width = max_dim;
-	S32 new_height = max_dim;
-
-	while( (new_width > getWidth()) && (new_width > MIN_IMAGE_SIZE) )
-	{
-		new_width >>= 1;
-	}
-
-	while( (new_height > getHeight()) && (new_height > MIN_IMAGE_SIZE) )
-	{
-		new_height >>= 1;
-	}
+	S32 new_width  = contractDimToPowerOfTwo(getWidth(), MIN_IMAGE_SIZE);
+	S32 new_height = contractDimToPowerOfTwo(getHeight(), MIN_IMAGE_SIZE);
 
 	scale( new_width, new_height, scale_image );
 }
 
-void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim)
+// static
+S32 LLImageRaw::biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim)
 {
 	// Strong bias towards rounding down (to save bandwidth)
 	// No bias would mean THRESHOLD == 1.5f;
-	const F32 THRESHOLD = 1.75f; 
-
+	const F32 THRESHOLD = 1.75f;
+    
 	// Find new sizes
-	S32 larger_w = max_dim;	// 2^n >= mWidth
-	S32 smaller_w = max_dim;	// 2^(n-1) <= mWidth
-	while( (smaller_w > getWidth()) && (smaller_w > MIN_IMAGE_SIZE) )
+	S32 larger_dim  = max_dim;	// 2^n >= curr_dim
+	S32 smaller_dim = max_dim;	// 2^(n-1) <= curr_dim
+	while( (smaller_dim > curr_dim) && (smaller_dim > MIN_IMAGE_SIZE) )
 	{
-		larger_w = smaller_w;
-		smaller_w >>= 1;
+		larger_dim = smaller_dim;
+		smaller_dim >>= 1;
 	}
-	S32 new_width = ( (F32)getWidth() / smaller_w > THRESHOLD ) ? larger_w : smaller_w;
+	return ( ((F32)curr_dim / (F32)smaller_dim) > THRESHOLD ) ? larger_dim : smaller_dim;
+}
 
+// static
+S32 LLImageRaw::expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim)
+{
+	S32 new_dim = MIN_IMAGE_SIZE;
+	while( (new_dim < curr_dim) && (new_dim < max_dim) )
+	{
+		new_dim <<= 1;
+	}
+    return new_dim;
+}
 
-	S32 larger_h = max_dim;	// 2^m >= mHeight
-	S32 smaller_h = max_dim;	// 2^(m-1) <= mHeight
-	while( (smaller_h > getHeight()) && (smaller_h > MIN_IMAGE_SIZE) )
+// static
+S32 LLImageRaw::contractDimToPowerOfTwo(S32 curr_dim, S32 min_dim)
+{
+	S32 new_dim = MAX_IMAGE_SIZE;
+	while( (new_dim > curr_dim) && (new_dim > min_dim) )
 	{
-		larger_h = smaller_h;
-		smaller_h >>= 1;
+		new_dim >>= 1;
 	}
-	S32 new_height = ( (F32)getHeight() / smaller_h > THRESHOLD ) ? larger_h : smaller_h;
+    return new_dim;
+}
 
+void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim)
+{
+	// Find new sizes
+	S32 new_width  = biasedDimToPowerOfTwo(getWidth(),max_dim);
+	S32 new_height = biasedDimToPowerOfTwo(getHeight(),max_dim);
 
 	scale( new_width, new_height );
 }
 
-
-
-
 // Calculates (U8)(255*(a/255.f)*(b/255.f) + 0.5f).  Thanks, Jim Blinn!
 inline U8 LLImageRaw::fastFractionalMult( U8 a, U8 b )
 {
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 2277afc585..c1ba1e3c21 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -205,6 +205,9 @@ public:
 
 	void verticalFlip();
 
+    static S32 biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
+    static S32 expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
+    static S32 contractDimToPowerOfTwo(S32 curr_dim, S32 min_dim = MIN_IMAGE_SIZE);
 	void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
 	void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
 	void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE);
diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 7bf74ef6ba..9676dfaf93 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -257,8 +257,6 @@ void LLFacebookPhotoPanel::draw()
 		gl_draw_scaled_image(offset_x, offset_y, 
 			thumbnail_w, thumbnail_h,
 			previewp->getThumbnailImage(), color % alpha);
-
-		previewp->drawPreviewRect(offset_x, offset_y) ;
 	}
 
     // Update the visibility of the working (computing preview) label
@@ -303,6 +301,7 @@ void LLFacebookPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
 			previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
 			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
 			previewp->setSnapshotQuality(mQuality, false);
+            previewp->setThumbnailSubsampled(TRUE);     // We want the preview to reflect the *saved* image
 			previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
 
 			updateControls();
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index c34124caf5..fbf4d758be 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -160,8 +160,6 @@ void LLFlickrPhotoPanel::draw()
 		gl_draw_scaled_image(offset_x, offset_y, 
 			thumbnail_w, thumbnail_h,
 			previewp->getThumbnailImage(), color % alpha);
-
-		previewp->drawPreviewRect(offset_x, offset_y) ;
 	}
 
     // Update the visibility of the working (computing preview) label
@@ -204,7 +202,7 @@ void LLFlickrPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
 
 			previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
 			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
-			//previewp->setSnapshotQuality(98);
+            previewp->setThumbnailSubsampled(TRUE);     // We want the preview to reflect the *saved* image
 			previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
 
 			updateControls();
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index c3efc26991..7ba5fc7b87 100755
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -436,9 +436,8 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
 	image_res_tb->setVisible(got_snap);
 	if (got_snap)
 	{
-		LLPointer<LLImageRaw> img = previewp->getEncodedImage();
-		image_res_tb->setTextArg("[WIDTH]", llformat("%d", img->getWidth()));
-		image_res_tb->setTextArg("[HEIGHT]", llformat("%d", img->getHeight()));
+		image_res_tb->setTextArg("[WIDTH]", llformat("%d", previewp->getEncodedImageWidth()));
+		image_res_tb->setTextArg("[HEIGHT]", llformat("%d", previewp->getEncodedImageHeight()));
 	}
 
 	floater->getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : floater->getString("unknown"));
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index ea263566a6..68bc4f1c3c 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -150,8 +150,6 @@ void LLTwitterPhotoPanel::draw()
 		gl_draw_scaled_image(offset_x, offset_y, 
 			thumbnail_w, thumbnail_h,
 			previewp->getThumbnailImage(), color % alpha);
-
-		previewp->drawPreviewRect(offset_x, offset_y) ;
 	}
 
     // Update the visibility of the working (computing preview) label
@@ -190,11 +188,11 @@ void LLTwitterPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
 			LLSnapshotLivePreview::Params p;
 			p.rect(full_screen_rect);
 			LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
-			mPreviewHandle = previewp->getHandle();	
+			mPreviewHandle = previewp->getHandle();
 
 			previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
 			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
-			//previewp->setSnapshotQuality(98);
+            previewp->setThumbnailSubsampled(TRUE);     // We want the preview to reflect the *saved* image
 			previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
 
 			updateControls();
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index ee74dbdb0f..4463dfdc38 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -78,6 +78,7 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param
 	mThumbnailImage(NULL) ,
 	mThumbnailWidth(0),
 	mThumbnailHeight(0),
+    mThumbnailSubsampled(FALSE),
 	mPreviewImageEncoded(NULL),
 	mFormattedImage(NULL),
 	mShineCountdown(0),
@@ -126,14 +127,7 @@ LLSnapshotLivePreview::~LLSnapshotLivePreview()
 
 void LLSnapshotLivePreview::setMaxImageSize(S32 size) 
 {
-	if(size < MAX_SNAPSHOT_IMAGE_SIZE)
-	{
-		mMaxImageSize = size;
-	}
-	else
-	{
-		mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ;
-	}
+    mMaxImageSize = llmin(size,(S32)(MAX_SNAPSHOT_IMAGE_SIZE));
 }
 
 LLViewerTexture* LLSnapshotLivePreview::getCurrentImage()
@@ -141,32 +135,17 @@ LLViewerTexture* LLSnapshotLivePreview::getCurrentImage()
 	return mViewerImage[mCurImageIndex];
 }
 
-F32 LLSnapshotLivePreview::getAspect()
-{
-	F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
-	F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
-
-	if (!mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
-	{
-		return image_aspect_ratio;
-	}
-	else
-	{
-		return window_aspect_ratio;
-	}
-}
-
 F32 LLSnapshotLivePreview::getImageAspect()
 {
 	if (!getCurrentImage())
 	{
 		return 0.f;
 	}
-
-	return getAspect() ;	
+	// mKeepAspectRatio) == gSavedSettings.getBOOL("KeepAspectForSnapshot"))
+    return (mKeepAspectRatio ? ((F32)getRect().getWidth()) / ((F32)getRect().getHeight()) : ((F32)getWidth()) / ((F32)getHeight()));
 }
 
-void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay) 
+void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay)
 {
 	// Invalidate current image.
 	lldebugs << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << llendl;
@@ -483,58 +462,49 @@ BOOL LLSnapshotLivePreview::setThumbnailImageSize()
 	{
 		return FALSE ;
 	}
-	S32 window_width = gViewerWindow->getWindowWidthRaw() ;
-	S32 window_height = gViewerWindow->getWindowHeightRaw() ;
+	S32 width  = (mThumbnailSubsampled ? mPreviewImage->getWidth()  : gViewerWindow->getWindowWidthRaw());
+	S32 height = (mThumbnailSubsampled ? mPreviewImage->getHeight() : gViewerWindow->getWindowHeightRaw()) ;
 
-	F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height);
+	F32 aspect_ratio = ((F32)width) / ((F32)height);
 
 	// UI size for thumbnail
 	// *FIXME: the rect does not change, so maybe there's no need to recalculate max w/h.
-	const LLRect& thumbnail_rect = mThumbnailPlaceholderRect;
-	S32 max_width = thumbnail_rect.getWidth();
-	S32 max_height = thumbnail_rect.getHeight();
+	//const LLRect& thumbnail_rect = mThumbnailPlaceholderRect;
+	S32 max_width  = mThumbnailPlaceholderRect.getWidth();
+	S32 max_height = mThumbnailPlaceholderRect.getHeight();
 
-	if (window_aspect_ratio > (F32)max_width / max_height)
+	if (aspect_ratio > (F32)max_width / (F32)max_height)
 	{
 		// image too wide, shrink to width
 		mThumbnailWidth = max_width;
-		mThumbnailHeight = llround((F32)max_width / window_aspect_ratio);
+		mThumbnailHeight = llround((F32)max_width / aspect_ratio);
 	}
 	else
 	{
 		// image too tall, shrink to height
 		mThumbnailHeight = max_height;
-		mThumbnailWidth = llround((F32)max_height * window_aspect_ratio);
+		mThumbnailWidth = llround((F32)max_height * aspect_ratio);
 	}
 
-	if(mThumbnailWidth > window_width || mThumbnailHeight > window_height)
+	if (mThumbnailWidth > width || mThumbnailHeight > height)
 	{
 		return FALSE ;//if the window is too small, ignore thumbnail updating.
 	}
 
 	S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0 ;
-	if(!mKeepAspectRatio)
+	if(!mKeepAspectRatio && !mThumbnailSubsampled)
 	{
-		F32 ratio_x = (F32)getWidth() / window_width ;
-		F32 ratio_y = (F32)getHeight() / window_height ;
+		F32 ratio_x = (F32)getWidth()  / width ;
+		F32 ratio_y = (F32)getHeight() / height ;
 
-		//if(getWidth() > window_width ||
-		//	getHeight() > window_height )
-		{
-			if(ratio_x > ratio_y)
-			{
-				top = (S32)(top * ratio_y / ratio_x) ;
-			}
-			else
-			{
-				right = (S32)(right * ratio_x / ratio_y) ;
-			}			
-		}
-		//else
-		//{
-		//	right = (S32)(right * ratio_x) ;
-		//	top = (S32)(top * ratio_y) ;
-		//}
+        if (ratio_x > ratio_y)
+        {
+            top = (S32)(top * ratio_y / ratio_x) ;
+        }
+        else
+        {
+            right = (S32)(right * ratio_x / ratio_y) ;
+        }
 		left = (S32)((mThumbnailWidth - right) * 0.5f) ;
 		bottom = (S32)((mThumbnailHeight - top) * 0.5f) ;
 		top += bottom ;
@@ -576,18 +546,41 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
 	}		
 
 	LLPointer<LLImageRaw> raw = new LLImageRaw;
-	if(!gViewerWindow->thumbnailSnapshot(raw,
-		mThumbnailWidth, mThumbnailHeight,
-		gSavedSettings.getBOOL("RenderUIInSnapshot"),
-		FALSE,
-		mSnapshotBufferType) )								
-	{
-		raw = NULL ;
-	}
-
-	if(raw)
+    
+    if (mThumbnailSubsampled)
+    {
+        // The thumbnail is be a subsampled version of the preview (used in SL Share previews, i.e. Flickr, Twitter, Facebook)
+		raw->resize( mPreviewImage->getWidth(),
+                     mPreviewImage->getHeight(),
+                     mPreviewImage->getComponents());
+        raw->copy(mPreviewImage);
+        // Scale to the thumbnal size modulo a power of 2
+        S32 width  = LLImageRaw::expandDimToPowerOfTwo(mThumbnailWidth,MAX_IMAGE_SIZE);
+        S32 height = LLImageRaw::expandDimToPowerOfTwo(mThumbnailHeight,MAX_IMAGE_SIZE);
+        if (!raw->scale(width, height))
+        {
+            raw = NULL ;
+        }
+    }
+    else
+    {
+        // The thumbnail is a screen view with screen grab positioning preview
+        if(!gViewerWindow->thumbnailSnapshot(raw,
+                                         mThumbnailWidth, mThumbnailHeight,
+                                         gSavedSettings.getBOOL("RenderUIInSnapshot"),
+                                         FALSE,
+                                         mSnapshotBufferType) )
+        {
+            raw = NULL ;
+        }
+        else
+        {
+            raw->expandToPowerOfTwo();
+        }
+    }
+    
+	if (raw)
 	{
-		raw->expandToPowerOfTwo();
         // Filter the thumbnail
         if (getFilter() != "")
         {
@@ -650,26 +643,22 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 	}
 
 	// time to produce a snapshot
-	previewp->setThumbnailImageSize();
+    //previewp->setThumbnailImageSize();
 
 	lldebugs << "producing snapshot" << llendl;
+	llinfos << "Merov : producing snapshot" << llendl;
 	if (!previewp->mPreviewImage)
 	{
 		previewp->mPreviewImage = new LLImageRaw;
 	}
 
-	if (!previewp->mPreviewImageEncoded)
-	{
-		previewp->mPreviewImageEncoded = new LLImageRaw;
-	}
-
 	previewp->setVisible(FALSE);
 	previewp->setEnabled(FALSE);
 
 	previewp->getWindow()->incBusyCount();
 	previewp->setImageScaled(FALSE);
 
-	// grab the raw image and encode it into desired format
+	// grab the raw image
 	if(gViewerWindow->rawSnapshot(
 		previewp->mPreviewImage,
 		previewp->getWidth(),
@@ -681,123 +670,60 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 		previewp->mSnapshotBufferType,
 		previewp->getMaxImageSize()))
 	{
-		previewp->mPreviewImageEncoded->resize(
-			previewp->mPreviewImage->getWidth(), 
-			previewp->mPreviewImage->getHeight(), 
-			previewp->mPreviewImage->getComponents());
+        // Invalidate/delete any existing encoded image
+        previewp->mPreviewImageEncoded = NULL;
+        // Invalidate/delete any existing formatted image
+        previewp->mFormattedImage = NULL;
+        // Update the data size
+        previewp->estimateDataSize();
 
-		if(previewp->getSnapshotType() == SNAPSHOT_TEXTURE)
-		{
-			lldebugs << "Encoding new image of format J2C" << llendl;
-			LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
-			LLPointer<LLImageRaw> scaled = new LLImageRaw(
-				previewp->mPreviewImage->getData(),
-				previewp->mPreviewImage->getWidth(),
-				previewp->mPreviewImage->getHeight(),
-				previewp->mPreviewImage->getComponents());
-
-			scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
-			previewp->setImageScaled(TRUE);
-			if (formatted->encode(scaled, 0.f))
-			{
-				previewp->mDataSize = formatted->getDataSize();
-				formatted->decode(previewp->mPreviewImageEncoded, 0);
-			}
-		}
-		else
-		{
-            // Apply the filter to mPreviewImage
-            if (previewp->getFilter() != "")
+        // Full size preview is set: get the decoded image result and save it for animation
+        if (gSavedSettings.getBOOL("UseFreezeFrame"))
+        {
+            // Get the decoded version of the formatted image
+            previewp->getEncodedImage();
+            
+            // We need to scale that a bit for display...
+            LLPointer<LLImageRaw> scaled = new LLImageRaw(
+                previewp->mPreviewImageEncoded->getData(),
+                previewp->mPreviewImageEncoded->getWidth(),
+			    previewp->mPreviewImageEncoded->getHeight(),
+			    previewp->mPreviewImageEncoded->getComponents());
+
+            if (!scaled->isBufferInvalid())
             {
-                std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(previewp->getFilter());
-                if (filter_path != "")
+                // leave original image dimensions, just scale up texture buffer
+                if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024)
                 {
-                    LLImageFilter filter(filter_path);
-                    filter.executeFilter(previewp->mPreviewImage);
+                    // go ahead and shrink image to appropriate power of 2 for display
+                    scaled->biasedScaleToPowerOfTwo(1024);
+                    previewp->setImageScaled(TRUE);
                 }
                 else
                 {
-                    llwarns << "Couldn't find a path to the following filter : " << previewp->getFilter() << llendl;
+                    // expand image but keep original image data intact
+                    scaled->expandToPowerOfTwo(1024, FALSE);
                 }
-            }
-            
-			// delete any existing image
-			previewp->mFormattedImage = NULL;
-			// now create the new one of the appropriate format.
-			LLFloaterSnapshot::ESnapshotFormat format = previewp->getSnapshotFormat();
-			lldebugs << "Encoding new image of format " << format << llendl;
 
-			switch(format)
-			{
-			case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
-				previewp->mFormattedImage = new LLImagePNG(); 
-				break;
-			case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
-				previewp->mFormattedImage = new LLImageJPEG(previewp->mSnapshotQuality); 
-				break;
-			case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
-				previewp->mFormattedImage = new LLImageBMP(); 
-				break;
-			}
-			if (previewp->mFormattedImage->encode(previewp->mPreviewImage, 0))
-			{
-				previewp->mDataSize = previewp->mFormattedImage->getDataSize();
-				// special case BMP to copy instead of decode otherwise decode will crash.
-				if(format == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP)
-				{
-					previewp->mPreviewImageEncoded->copy(previewp->mPreviewImage);
-				}
-				else
-				{
-					previewp->mFormattedImage->decode(previewp->mPreviewImageEncoded, 0);
-				}
-			}
-		}
+                previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
+                LLPointer<LLViewerTexture> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex];
+                gGL.getTexUnit(0)->bind(curr_preview_image);
+                curr_preview_image->setFilteringOption(previewp->getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT);
+                curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);
 
-		LLPointer<LLImageRaw> scaled = new LLImageRaw(
-			previewp->mPreviewImageEncoded->getData(),
-			previewp->mPreviewImageEncoded->getWidth(),
-			previewp->mPreviewImageEncoded->getHeight(),
-			previewp->mPreviewImageEncoded->getComponents());
-
-		if(!scaled->isBufferInvalid())
-		{
-			// leave original image dimensions, just scale up texture buffer
-			if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024)
-			{
-				// go ahead and shrink image to appropriate power of 2 for display
-				scaled->biasedScaleToPowerOfTwo(1024);
-				previewp->setImageScaled(TRUE);
-			}
-			else
-			{
-				// expand image but keep original image data intact
-				scaled->expandToPowerOfTwo(1024, FALSE);
-			}
-
-			previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
-			LLPointer<LLViewerTexture> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex];
-			gGL.getTexUnit(0)->bind(curr_preview_image);
-			if (previewp->getSnapshotType() != SNAPSHOT_TEXTURE)
-			{
-				curr_preview_image->setFilteringOption(LLTexUnit::TFO_POINT);
-			}
-			else
-			{
-				curr_preview_image->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
-			}
-			curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);
-
-			previewp->mSnapshotUpToDate = TRUE;
-			previewp->generateThumbnailImage(TRUE) ;
-
-			previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal();
-			previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
-		}
+                previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal();
+                previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
+            }
+        }
+        // K, the snapshot is updated...
+        previewp->mSnapshotUpToDate = TRUE;
+        
+        // We need to update the thumbnail though
+        previewp->setThumbnailImageSize();
+        previewp->generateThumbnailImage(TRUE) ;
 	}
 	previewp->getWindow()->decBusyCount();
-	// only show fullscreen preview when in freeze frame mode
-	previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame"));
+	previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame")); // only show fullscreen preview when in freeze frame mode
 	previewp->mSnapshotDelayTimer.stop();
 	previewp->mSnapshotActive = FALSE;
 
@@ -806,6 +732,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 		previewp->generateThumbnailImage() ;
 	}
 	lldebugs << "done creating snapshot" << llendl;
+	llinfos << "Merov : Done creating snapshot" << llendl;
 	LLFloaterSnapshot::postUpdate();
 	LLFloaterFacebook::postUpdate();
 	LLFloaterFlickr::postUpdate();
@@ -814,6 +741,153 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 	return TRUE;
 }
 
+S32 LLSnapshotLivePreview::getEncodedImageWidth() const
+{
+    S32 width = getWidth();
+    if (getSnapshotType() == SNAPSHOT_TEXTURE)
+    {
+        width = LLImageRaw::biasedDimToPowerOfTwo(width,MAX_TEXTURE_SIZE);
+    }
+    return width;
+}
+S32 LLSnapshotLivePreview::getEncodedImageHeight() const
+{
+    S32 height = getHeight();
+    if (getSnapshotType() == SNAPSHOT_TEXTURE)
+    {
+        height = LLImageRaw::biasedDimToPowerOfTwo(height,MAX_TEXTURE_SIZE);
+    }
+    return height;
+}
+
+LLPointer<LLImageRaw> LLSnapshotLivePreview::getEncodedImage()
+{
+	if (!mPreviewImageEncoded)
+	{
+		mPreviewImageEncoded = new LLImageRaw;
+    
+		mPreviewImageEncoded->resize(
+            mPreviewImage->getWidth(),
+            mPreviewImage->getHeight(),
+            mPreviewImage->getComponents());
+        
+		if (getSnapshotType() == SNAPSHOT_TEXTURE)
+		{
+            // We don't store the intermediate formatted image in mFormattedImage in the J2C case 
+			lldebugs << "Encoding new image of format J2C" << llendl;
+			LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
+            // Copy the preview
+			LLPointer<LLImageRaw> scaled = new LLImageRaw(
+                                                          mPreviewImage->getData(),
+                                                          mPreviewImage->getWidth(),
+                                                          mPreviewImage->getHeight(),
+                                                          mPreviewImage->getComponents());
+            // Scale it as required by J2C
+			scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
+			setImageScaled(TRUE);
+            // Compress to J2C
+			if (formatted->encode(scaled, 0.f))
+			{
+                // We can update the data size precisely at that point
+				mDataSize = formatted->getDataSize();
+                // Decompress back
+				formatted->decode(mPreviewImageEncoded, 0);
+			}
+		}
+		else
+		{
+            // Update mFormattedImage if necessary
+            getFormattedImage();
+            if (getSnapshotFormat() == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP)
+            {
+                // BMP hack : copy instead of decode otherwise decode will crash.
+                mPreviewImageEncoded->copy(mPreviewImage);
+            }
+            else
+            {
+                // Decode back
+                mFormattedImage->decode(mPreviewImageEncoded, 0);
+            }
+		}
+	}
+    return mPreviewImageEncoded;
+}
+
+// We actually estimate the data size so that we do not require actual compression when showing the preview
+// Note : whenever formatted image is computed, mDataSize will be updated to reflect the true size
+void LLSnapshotLivePreview::estimateDataSize()
+{
+    // Compression ratio
+    F32 ratio = 1.0;
+    
+    if (getSnapshotType() == SNAPSHOT_TEXTURE)
+    {
+        ratio = 8.0;    // This is what we shoot for when compressing to J2C
+    }
+    else
+    {
+        LLFloaterSnapshot::ESnapshotFormat format = getSnapshotFormat();
+        switch (format)
+        {
+            case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
+                ratio = 3.0;    // Average observed PNG compression ratio
+                break;
+            case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
+                // Observed from JPG compression tests
+                ratio = (110 - mSnapshotQuality) / 2;
+                break;
+            case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
+                ratio = 1.0;    // No compression with BMP
+                break;
+        }
+    }
+    mDataSize = (S32)((F32)mPreviewImage->getDataSize() / ratio);
+}
+
+LLPointer<LLImageFormatted>	LLSnapshotLivePreview::getFormattedImage()
+{
+    if (!mFormattedImage)
+    {
+        // Apply the filter to mPreviewImage
+        if (getFilter() != "")
+        {
+            std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter());
+            if (filter_path != "")
+            {
+                LLImageFilter filter(filter_path);
+                filter.executeFilter(mPreviewImage);
+            }
+            else
+            {
+                llwarns << "Couldn't find a path to the following filter : " << getFilter() << llendl;
+            }
+        }
+        
+        // Create the new formatted image of the appropriate format.
+        LLFloaterSnapshot::ESnapshotFormat format = getSnapshotFormat();
+        lldebugs << "Encoding new image of format " << format << llendl;
+            
+        switch (format)
+        {
+            case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
+                mFormattedImage = new LLImagePNG();
+                break;
+            case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
+                mFormattedImage = new LLImageJPEG(mSnapshotQuality);
+                break;
+            case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
+                mFormattedImage = new LLImageBMP();
+                break;
+        }
+        if (mFormattedImage->encode(mPreviewImage, 0))
+        {
+            // We can update the data size precisely at that point
+            mDataSize = mFormattedImage->getDataSize();
+        }
+    }
+    return mFormattedImage;
+}
+
 void LLSnapshotLivePreview::setSize(S32 w, S32 h)
 {
 	lldebugs << "setSize(" << w << ", " << h << ")" << llendl;
@@ -875,12 +949,14 @@ void LLSnapshotLivePreview::saveTexture()
 	}
 
 	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_SNAPSHOT_COUNT );
-
-	mDataSize = 0;
 }
 
 BOOL LLSnapshotLivePreview::saveLocal()
 {
+    // Update mFormattedImage if necessary
+    getFormattedImage();
+    
+    // Save the formatted image
 	BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage);
 
 	if(success)
@@ -892,6 +968,9 @@ BOOL LLSnapshotLivePreview::saveLocal()
 
 void LLSnapshotLivePreview::saveWeb()
 {
+    // Update mFormattedImage if necessary
+    getFormattedImage();
+    
 	// *FIX: Will break if the window closes because of CloseSnapshotOnKeep!
 	// Needs to pass on ownership of the image.
 	LLImageJPEG* jpg = dynamic_cast<LLImageJPEG*>(mFormattedImage.get());
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index 6addc87de2..4fd6dedeed 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -70,6 +70,9 @@ public:
 	void getSize(S32& w, S32& h) const;
 	S32 getWidth() const { return mWidth[mCurImageIndex]; }
 	S32 getHeight() const { return mHeight[mCurImageIndex]; }
+    S32 getEncodedImageWidth() const;
+    S32 getEncodedImageHeight() const;
+    void estimateDataSize();
 	S32 getDataSize() const { return mDataSize; }
 	void setMaxImageSize(S32 size) ;
 	S32  getMaxImageSize() {return mMaxImageSize ;}
@@ -83,9 +86,10 @@ public:
 	S32  getThumbnailHeight() const { return mThumbnailHeight ; }
 	BOOL getThumbnailLock() const { return mThumbnailUpdateLock ; }
 	BOOL getThumbnailUpToDate() const { return mThumbnailUpToDate ;}
+    void setThumbnailSubsampled(BOOL subsampled) { mThumbnailSubsampled = subsampled; }
+
 	LLViewerTexture* getCurrentImage();
 	F32 getImageAspect();
-	F32 getAspect() ;
 	const LLRect& getImageRect() const { return mImageRect[mCurImageIndex]; }
 	BOOL isImageScaled() const { return mImageScaled[mCurImageIndex]; }
 	void setImageScaled(BOOL scaled) { mImageScaled[mCurImageIndex] = scaled; }
@@ -96,14 +100,14 @@ public:
 	bool setSnapshotQuality(S32 quality, bool set_by_user = true);
 	void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
     void setFilter(std::string filter_name) { mFilterName = filter_name; }
-    std::string  getFilter() { return mFilterName; }
+    std::string  getFilter() const { return mFilterName; }
 	void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f);
 	void saveWeb();
 	void saveTexture();
 	BOOL saveLocal();
 
-	LLPointer<LLImageFormatted>	getFormattedImage() const { return mFormattedImage; }
-	LLPointer<LLImageRaw>		getEncodedImage() const { return mPreviewImageEncoded; }
+	LLPointer<LLImageFormatted>	getFormattedImage();
+	LLPointer<LLImageRaw>		getEncodedImage();
 
 	/// Sets size of preview thumbnail image and thhe surrounding rect.
 	void setThumbnailPlaceholderRect(const LLRect& rect) {mThumbnailPlaceholderRect = rect; }
@@ -135,8 +139,10 @@ private:
 	BOOL                        mThumbnailUpdateLock ;
 	BOOL                        mThumbnailUpToDate ;
 	LLRect                      mThumbnailPlaceholderRect;
+    BOOL                        mThumbnailSubsampled; // TRUE is the thumbnail is a subsampled version of the mPreviewImage
 
 	S32							mCurImageIndex;
+    // The logic is mPreviewImage (raw frame) -> mFormattedImage (formatted / filtered) -> mPreviewImageEncoded (decoded back, to show artifacts)
 	LLPointer<LLImageRaw>		mPreviewImage;
 	LLPointer<LLImageRaw>		mPreviewImageEncoded;
 	LLPointer<LLImageFormatted>	mFormattedImage;
-- 
cgit v1.2.3


From 6dfba5829e3f9cf5986c627b537da55cf84c84c7 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 28 Jan 2014 13:38:12 -0800
Subject: ACME-1195 : Make SL Share snapshot use faster thumbnail computation
 and display

---
 indra/newview/llsnapshotlivepreview.cpp | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 4463dfdc38..04dd86a77d 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -458,7 +458,7 @@ void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_pare
 
 BOOL LLSnapshotLivePreview::setThumbnailImageSize()
 {
-	if(getWidth() < 10 || getHeight() < 10)
+	if (getWidth() < 10 || getHeight() < 10)
 	{
 		return FALSE ;
 	}
@@ -468,8 +468,6 @@ BOOL LLSnapshotLivePreview::setThumbnailImageSize()
 	F32 aspect_ratio = ((F32)width) / ((F32)height);
 
 	// UI size for thumbnail
-	// *FIXME: the rect does not change, so maybe there's no need to recalculate max w/h.
-	//const LLRect& thumbnail_rect = mThumbnailPlaceholderRect;
 	S32 max_width  = mThumbnailPlaceholderRect.getWidth();
 	S32 max_height = mThumbnailPlaceholderRect.getHeight();
 
@@ -485,14 +483,14 @@ BOOL LLSnapshotLivePreview::setThumbnailImageSize()
 		mThumbnailHeight = max_height;
 		mThumbnailWidth = llround((F32)max_height * aspect_ratio);
 	}
-
+    
 	if (mThumbnailWidth > width || mThumbnailHeight > height)
 	{
 		return FALSE ;//if the window is too small, ignore thumbnail updating.
 	}
 
 	S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0 ;
-	if(!mKeepAspectRatio && !mThumbnailSubsampled)
+	if (!mKeepAspectRatio)
 	{
 		F32 ratio_x = (F32)getWidth()  / width ;
 		F32 ratio_y = (F32)getHeight() / height ;
@@ -643,10 +641,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 	}
 
 	// time to produce a snapshot
-    //previewp->setThumbnailImageSize();
-
 	lldebugs << "producing snapshot" << llendl;
-	llinfos << "Merov : producing snapshot" << llendl;
 	if (!previewp->mPreviewImage)
 	{
 		previewp->mPreviewImage = new LLImageRaw;
@@ -732,7 +727,6 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 		previewp->generateThumbnailImage() ;
 	}
 	lldebugs << "done creating snapshot" << llendl;
-	llinfos << "Merov : Done creating snapshot" << llendl;
 	LLFloaterSnapshot::postUpdate();
 	LLFloaterFacebook::postUpdate();
 	LLFloaterFlickr::postUpdate();
-- 
cgit v1.2.3


From b35889a6510440692be4b7f1aa590cf645fbba90 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 28 Jan 2014 17:45:48 -0800
Subject: ACME-1195 : Complete perf improvements. Also we do not regrab/refresh
 when we don't have to (e.g. change format) in particular when changing
 filter. Better control that way and faster UI.

---
 indra/newview/llfloaterfacebook.cpp     |  17 +--
 indra/newview/llfloaterflickr.cpp       |  27 ++--
 indra/newview/llfloatersnapshot.cpp     |  15 +-
 indra/newview/llfloatertwitter.cpp      |  15 +-
 indra/newview/llsnapshotlivepreview.cpp | 244 +++++++++++++++++---------------
 indra/newview/llsnapshotlivepreview.h   |   2 +-
 6 files changed, 154 insertions(+), 166 deletions(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 9676dfaf93..1cd7ecbcd8 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -314,8 +314,6 @@ void LLFacebookPhotoPanel::onClickNewSnapshot()
 	LLSnapshotLivePreview* previewp = getPreviewView();
 	if (previewp)
 	{
-		//setStatus(Impl::STATUS_READY);
-		lldebugs << "updating snapshot" << llendl;
 		previewp->updateSnapshot(TRUE);
 	}
 }
@@ -461,24 +459,17 @@ void LLFacebookPhotoPanel::updateResolution(BOOL do_update)
         
         // Recompute quality setting
         mQuality = compute_jpeg_quality(width, height);
-        bool quality_reset = previewp->setSnapshotQuality(mQuality, false);
+        previewp->setSnapshotQuality(mQuality, false);
 		
-		if (original_width != width || original_height != height || quality_reset)
+		if (original_width != width || original_height != height)
 		{
 			previewp->setSize(width, height);
-
-			// hide old preview as the aspect ratio could be wrong
-			lldebugs << "updating thumbnail" << llendl;
-			
-			previewp->updateSnapshot(FALSE, TRUE);
-			if (do_update || quality_reset)
+			if (do_update)
 			{
-				lldebugs << "Will update controls" << llendl;
+                previewp->updateSnapshot(TRUE);
 				updateControls();
-                LLFacebookPhotoPanel::onClickNewSnapshot();
 			}
 		}
-		
 	}
 }
 
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index fbf4d758be..2dc62dcda8 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -215,8 +215,6 @@ void LLFlickrPhotoPanel::onClickNewSnapshot()
 	LLSnapshotLivePreview* previewp = getPreviewView();
 	if (previewp)
 	{
-		//setStatus(Impl::STATUS_READY);
-		lldebugs << "updating snapshot" << llendl;
 		previewp->updateSnapshot(TRUE);
 	}
 }
@@ -355,27 +353,26 @@ void LLFlickrPhotoPanel::updateResolution(BOOL do_update)
 		checkAspectRatio(width);
 
 		previewp->getSize(width, height);
+		if ((original_width != width) || (original_height != height))
+		{
+			previewp->setSize(width, height);
+			if (do_update)
+			{
+                previewp->updateSnapshot(TRUE);
+				updateControls();
+			}
+		}
         // Get the old filter, compare to the current one "filter_name" and set if changed
-        // If changed, also force the updateSnapshot() here under
         std::string original_filter = previewp->getFilter();
-		
-		if ((original_width != width) || (original_height != height) || (original_filter != filter_name))
+		if (original_filter != filter_name)
 		{
-			previewp->setSize(width, height);
             previewp->setFilter(filter_name);
-
-			// hide old preview as the aspect ratio could be wrong
-			lldebugs << "updating thumbnail" << llendl;
-			
-			previewp->updateSnapshot(FALSE, TRUE);
-			if(do_update)
+			if (do_update)
 			{
-				lldebugs << "Will update controls" << llendl;
+                previewp->updateSnapshot(FALSE, TRUE);
 				updateControls();
-                LLFlickrPhotoPanel::onClickNewSnapshot();
 			}
 		}
-		
 	}
 }
 
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 7ba5fc7b87..27a9e3da44 100755
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -622,9 +622,9 @@ void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL
 			previewp->getSize(w, h) ;
 			updateSpinners(view, previewp, w, h, TRUE); // may change w and h
 
-			lldebugs << "updating thumbnail" << llendl;
+			lldebugs << "updating snapshot" << llendl;
 			previewp->setSize(w, h) ;
-			previewp->updateSnapshot(FALSE, TRUE);
+			previewp->updateSnapshot(TRUE);
 			checkAutoSnapshot(previewp, TRUE);
 		}
 	}
@@ -821,8 +821,8 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL
 
 			// hide old preview as the aspect ratio could be wrong
 			checkAutoSnapshot(previewp, FALSE);
-			lldebugs << "updating thumbnail" << llendl;
-			getPreviewView(view)->updateSnapshot(FALSE, TRUE);
+			lldebugs << "updating snapshot" << llendl;
+			getPreviewView(view)->updateSnapshot(TRUE);
 			if(do_update)
 			{
 				lldebugs << "Will update controls" << llendl;
@@ -859,7 +859,6 @@ void LLFloaterSnapshot::Impl::onImageQualityChange(LLFloaterSnapshot* view, S32
 	{
 		previewp->setSnapshotQuality(quality_val);
 	}
-	checkAutoSnapshot(previewp, TRUE);
 }
 
 // static
@@ -868,8 +867,6 @@ void LLFloaterSnapshot::Impl::onImageFormatChange(LLFloaterSnapshot* view)
 	if (view)
 	{
 		gSavedSettings.setS32("SnapshotFormat", getImageFormat(view));
-		lldebugs << "image format changed, updating snapshot" << llendl;
-		getPreviewView(view)->updateSnapshot(TRUE);
 		updateControls(view);
 		setNeedRefresh(view, false); // we're refreshing
 	}
@@ -969,8 +966,8 @@ void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32
 
 			previewp->setSize(w,h);
 			checkAutoSnapshot(previewp, FALSE);
-			lldebugs << "applied custom resolution, updating thumbnail" << llendl;
-			previewp->updateSnapshot(FALSE, TRUE);
+			lldebugs << "applied custom resolution, updating snapshot" << llendl;
+			previewp->updateSnapshot(TRUE);
 			comboSetCustom(view, "profile_size_combo");
 			comboSetCustom(view, "postcard_size_combo");
 			comboSetCustom(view, "texture_size_combo");
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index 68bc4f1c3c..5e0f652264 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -217,8 +217,6 @@ void LLTwitterPhotoPanel::onClickNewSnapshot()
 	LLSnapshotLivePreview* previewp = getPreviewView();
 	if (previewp)
 	{
-		//setStatus(Impl::STATUS_READY);
-		lldebugs << "updating snapshot" << llendl;
 		previewp->updateSnapshot(TRUE);
 	}
 }
@@ -417,22 +415,15 @@ void LLTwitterPhotoPanel::updateResolution(BOOL do_update)
 
 		previewp->getSize(width, height);
 		
-		if(original_width != width || original_height != height)
+		if (original_width != width || original_height != height)
 		{
 			previewp->setSize(width, height);
-
-			// hide old preview as the aspect ratio could be wrong
-			lldebugs << "updating thumbnail" << llendl;
-			
-			previewp->updateSnapshot(FALSE, TRUE);
-			if(do_update)
+			if (do_update)
 			{
-				lldebugs << "Will update controls" << llendl;
+                previewp->updateSnapshot(TRUE);
 				updateControls();
-                LLTwitterPhotoPanel::onClickNewSnapshot();
 			}
 		}
-		
 	}
 }
 
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 04dd86a77d..0d1562b6d4 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -147,48 +147,48 @@ F32 LLSnapshotLivePreview::getImageAspect()
 
 void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay)
 {
-	// Invalidate current image.
 	lldebugs << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << llendl;
-	if (getSnapshotUpToDate())
+
+	// Update snapshot if requested.
+	if (new_snapshot)
 	{
-		S32 old_image_index = mCurImageIndex;
-		mCurImageIndex = (mCurImageIndex + 1) % 2; 
-		setSize(mWidth[old_image_index], mHeight[old_image_index]);
-		mFallAnimTimer.start();		
-	}
-	mSnapshotUpToDate = FALSE; 		
+        if (getSnapshotUpToDate())
+        {
+            S32 old_image_index = mCurImageIndex;
+            mCurImageIndex = (mCurImageIndex + 1) % 2; 
+            setSize(mWidth[old_image_index], mHeight[old_image_index]);
+            mFallAnimTimer.start();		
+        }
+        mSnapshotUpToDate = FALSE; 		
 
-	// Update snapshot source rect depending on whether we keep the aspect ratio.
-	LLRect& rect = mImageRect[mCurImageIndex];
-	rect.set(0, getRect().getHeight(), getRect().getWidth(), 0);
+        // Update snapshot source rect depending on whether we keep the aspect ratio.
+        LLRect& rect = mImageRect[mCurImageIndex];
+        rect.set(0, getRect().getHeight(), getRect().getWidth(), 0);
 
-	F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
-	F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
+        F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
+        F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
 
-	if (mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
-	{
-		if (image_aspect_ratio > window_aspect_ratio)
-		{
-			// trim off top and bottom
-			S32 new_height = llround((F32)getRect().getWidth() / image_aspect_ratio); 
-			rect.mBottom += (getRect().getHeight() - new_height) / 2;
-			rect.mTop -= (getRect().getHeight() - new_height) / 2;
-		}
-		else if (image_aspect_ratio < window_aspect_ratio)
-		{
-			// trim off left and right
-			S32 new_width = llround((F32)getRect().getHeight() * image_aspect_ratio); 
-			rect.mLeft += (getRect().getWidth() - new_width) / 2;
-			rect.mRight -= (getRect().getWidth() - new_width) / 2;
-		}
-	}
+        if (mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
+        {
+            if (image_aspect_ratio > window_aspect_ratio)
+            {
+                // trim off top and bottom
+                S32 new_height = llround((F32)getRect().getWidth() / image_aspect_ratio); 
+                rect.mBottom += (getRect().getHeight() - new_height) / 2;
+                rect.mTop -= (getRect().getHeight() - new_height) / 2;
+            }
+            else if (image_aspect_ratio < window_aspect_ratio)
+            {
+                // trim off left and right
+                S32 new_width = llround((F32)getRect().getHeight() * image_aspect_ratio); 
+                rect.mLeft += (getRect().getWidth() - new_width) / 2;
+                rect.mRight -= (getRect().getWidth() - new_width) / 2;
+            }
+        }
 
-	// Stop shining animation.
-	mShineAnimTimer.stop();
+        // Stop shining animation.
+        mShineAnimTimer.stop();
 
-	// Update snapshot if requested.
-	if (new_snapshot)
-	{
 		mSnapshotDelayTimer.start();
 		mSnapshotDelayTimer.setTimerExpirySec(delay);
 		LLFloaterSnapshot::preUpdate();
@@ -198,7 +198,7 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail
 	}
 
 	// Update thumbnail if requested.
-	if(new_thumbnail)
+	if (new_thumbnail)
 	{
 		mThumbnailUpToDate = FALSE ;
 	}
@@ -215,7 +215,7 @@ bool LLSnapshotLivePreview::setSnapshotQuality(S32 quality, bool set_by_user)
         {
             gSavedSettings.setS32("SnapshotQuality", quality);
         }
-		mSnapshotUpToDate = FALSE;
+        mFormattedImage = NULL;     // Invalidate the already formatted image if any
         return true;
 	}
     return false;
@@ -451,8 +451,8 @@ void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_pare
 	LLView::reshape(width, height, called_from_parent);
 	if (old_rect.getWidth() != width || old_rect.getHeight() != height)
 	{
-		lldebugs << "window reshaped, updating thumbnail" << llendl;
-		updateSnapshot(FALSE, TRUE);
+		lldebugs << "window reshaped, updating snapshot" << llendl;
+		updateSnapshot(TRUE);
 	}
 }
 
@@ -635,98 +635,101 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 	previewp->mSnapshotActive = 
 		(previewp->mSnapshotDelayTimer.getStarted() &&	previewp->mSnapshotDelayTimer.hasExpired())
 		&& !LLToolCamera::getInstance()->hasMouseCapture(); // don't take snapshots while ALT-zoom active
-	if ( ! previewp->mSnapshotActive)
+	if (!previewp->mSnapshotActive && previewp->getSnapshotUpToDate() && previewp->getThumbnailUpToDate())
 	{
 		return FALSE;
 	}
 
 	// time to produce a snapshot
-	lldebugs << "producing snapshot" << llendl;
-	if (!previewp->mPreviewImage)
-	{
-		previewp->mPreviewImage = new LLImageRaw;
-	}
+	if(!previewp->getSnapshotUpToDate())
+    {
+        lldebugs << "producing snapshot" << llendl;
+        if (!previewp->mPreviewImage)
+        {
+            previewp->mPreviewImage = new LLImageRaw;
+        }
 
-	previewp->setVisible(FALSE);
-	previewp->setEnabled(FALSE);
-
-	previewp->getWindow()->incBusyCount();
-	previewp->setImageScaled(FALSE);
-
-	// grab the raw image
-	if(gViewerWindow->rawSnapshot(
-		previewp->mPreviewImage,
-		previewp->getWidth(),
-		previewp->getHeight(),
-		previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"),
-		previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE,
-		gSavedSettings.getBOOL("RenderUIInSnapshot"),
-		FALSE,
-		previewp->mSnapshotBufferType,
-		previewp->getMaxImageSize()))
-	{
-        // Invalidate/delete any existing encoded image
-        previewp->mPreviewImageEncoded = NULL;
-        // Invalidate/delete any existing formatted image
-        previewp->mFormattedImage = NULL;
-        // Update the data size
-        previewp->estimateDataSize();
-
-        // Full size preview is set: get the decoded image result and save it for animation
-        if (gSavedSettings.getBOOL("UseFreezeFrame"))
+        previewp->setVisible(FALSE);
+        previewp->setEnabled(FALSE);
+
+        previewp->getWindow()->incBusyCount();
+        previewp->setImageScaled(FALSE);
+
+        // grab the raw image
+        if (gViewerWindow->rawSnapshot(
+                previewp->mPreviewImage,
+                previewp->getWidth(),
+                previewp->getHeight(),
+                previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"),
+                previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE,
+                gSavedSettings.getBOOL("RenderUIInSnapshot"),
+                FALSE,
+                previewp->mSnapshotBufferType,
+                previewp->getMaxImageSize()))
         {
-            // Get the decoded version of the formatted image
-            previewp->getEncodedImage();
-            
-            // We need to scale that a bit for display...
-            LLPointer<LLImageRaw> scaled = new LLImageRaw(
-                previewp->mPreviewImageEncoded->getData(),
-                previewp->mPreviewImageEncoded->getWidth(),
-			    previewp->mPreviewImageEncoded->getHeight(),
-			    previewp->mPreviewImageEncoded->getComponents());
-
-            if (!scaled->isBufferInvalid())
+            // Invalidate/delete any existing encoded image
+            previewp->mPreviewImageEncoded = NULL;
+            // Invalidate/delete any existing formatted image
+            previewp->mFormattedImage = NULL;
+            // Update the data size
+            previewp->estimateDataSize();
+
+            // Full size preview is set: get the decoded image result and save it for animation
+            if (gSavedSettings.getBOOL("UseFreezeFrame"))
             {
-                // leave original image dimensions, just scale up texture buffer
-                if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024)
-                {
-                    // go ahead and shrink image to appropriate power of 2 for display
-                    scaled->biasedScaleToPowerOfTwo(1024);
-                    previewp->setImageScaled(TRUE);
-                }
-                else
+                // Get the decoded version of the formatted image
+                previewp->getEncodedImage();
+            
+                // We need to scale that a bit for display...
+                LLPointer<LLImageRaw> scaled = new LLImageRaw(
+                    previewp->mPreviewImageEncoded->getData(),
+                    previewp->mPreviewImageEncoded->getWidth(),
+                    previewp->mPreviewImageEncoded->getHeight(),
+                    previewp->mPreviewImageEncoded->getComponents());
+
+                if (!scaled->isBufferInvalid())
                 {
-                    // expand image but keep original image data intact
-                    scaled->expandToPowerOfTwo(1024, FALSE);
+                    // leave original image dimensions, just scale up texture buffer
+                    if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024)
+                    {
+                        // go ahead and shrink image to appropriate power of 2 for display
+                        scaled->biasedScaleToPowerOfTwo(1024);
+                        previewp->setImageScaled(TRUE);
+                    }
+                    else
+                    {
+                        // expand image but keep original image data intact
+                        scaled->expandToPowerOfTwo(1024, FALSE);
+                    }
+
+                    previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
+                    LLPointer<LLViewerTexture> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex];
+                    gGL.getTexUnit(0)->bind(curr_preview_image);
+                    curr_preview_image->setFilteringOption(previewp->getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT);
+                    curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);
+
+                    previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal();
+                    previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
                 }
-
-                previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
-                LLPointer<LLViewerTexture> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex];
-                gGL.getTexUnit(0)->bind(curr_preview_image);
-                curr_preview_image->setFilteringOption(previewp->getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT);
-                curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);
-
-                previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal();
-                previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
             }
-        }
-        // K, the snapshot is updated...
-        previewp->mSnapshotUpToDate = TRUE;
+            // The snapshot is updated now...
+            previewp->mSnapshotUpToDate = TRUE;
         
-        // We need to update the thumbnail though
-        previewp->setThumbnailImageSize();
-        previewp->generateThumbnailImage(TRUE) ;
-	}
-	previewp->getWindow()->decBusyCount();
-	previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame")); // only show fullscreen preview when in freeze frame mode
-	previewp->mSnapshotDelayTimer.stop();
-	previewp->mSnapshotActive = FALSE;
-
-	if(!previewp->getThumbnailUpToDate())
+            // We need to update the thumbnail though
+            previewp->setThumbnailImageSize();
+            previewp->generateThumbnailImage(TRUE) ;
+        }
+        previewp->getWindow()->decBusyCount();
+        previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame")); // only show fullscreen preview when in freeze frame mode
+        previewp->mSnapshotDelayTimer.stop();
+        previewp->mSnapshotActive = FALSE;
+        lldebugs << "done creating snapshot" << llendl;
+    }
+    
+    if (!previewp->getThumbnailUpToDate())
 	{
 		previewp->generateThumbnailImage() ;
 	}
-	lldebugs << "done creating snapshot" << llendl;
 	LLFloaterSnapshot::postUpdate();
 	LLFloaterFacebook::postUpdate();
 	LLFloaterFlickr::postUpdate();
@@ -889,6 +892,15 @@ void LLSnapshotLivePreview::setSize(S32 w, S32 h)
 	setHeight(h);
 }
 
+void LLSnapshotLivePreview::setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat format)
+{
+    if (mSnapshotFormat != format)
+    {
+        mFormattedImage = NULL;     // Invalidate the already formatted image if any
+        mSnapshotFormat = format;
+    }
+}
+
 void LLSnapshotLivePreview::getSize(S32& w, S32& h) const
 {
 	w = getWidth();
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index 4fd6dedeed..10f20e7fe8 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -96,7 +96,7 @@ public:
 	const LLVector3d& getPosTakenGlobal() const { return mPosTakenGlobal; }
 
 	void setSnapshotType(ESnapshotType type) { mSnapshotType = type; }
-	void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; }
+	void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat format);
 	bool setSnapshotQuality(S32 quality, bool set_by_user = true);
 	void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
     void setFilter(std::string filter_name) { mFilterName = filter_name; }
-- 
cgit v1.2.3


From f7a90c680a007775efe0f8556c6712a08e489aab Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 28 Jan 2014 19:00:46 -0800
Subject: ACME-1275 : Implemented filters to the Twitter and Facebook panels

---
 indra/newview/llfloaterfacebook.cpp                | 45 +++++++++++++---------
 indra/newview/llfloaterfacebook.h                  |  1 +
 indra/newview/llfloatertwitter.cpp                 | 45 +++++++++++++---------
 indra/newview/llfloatertwitter.h                   |  1 +
 .../skins/default/xui/en/panel_facebook_photo.xml  | 27 ++++++-------
 .../skins/default/xui/en/panel_twitter_photo.xml   | 27 ++++++-------
 6 files changed, 84 insertions(+), 62 deletions(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 1cd7ecbcd8..f86b6d580a 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -36,6 +36,7 @@
 #include "llfacebookconnect.h"
 #include "llfloaterreg.h"
 #include "lliconctrl.h"
+#include "llimagefiltersmanager.h"
 #include "llresmgr.h"		// LLLocale
 #include "llsdserialize.h"
 #include "llloadingindicator.h"
@@ -207,6 +208,8 @@ BOOL LLFacebookPhotoPanel::postBuild()
 	mSnapshotPanel = getChild<LLUICtrl>("snapshot_panel");
 	mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
 	mResolutionComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE));
+	mFilterComboBox = getChild<LLUICtrl>("filters_combobox");
+	mFilterComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE));
 	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
     mWorkingLabel = getChild<LLUICtrl>("working_lbl");
 	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
@@ -215,6 +218,14 @@ BOOL LLFacebookPhotoPanel::postBuild()
 	mPostButton = getChild<LLUICtrl>("post_photo_btn");
 	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
 
+	// Update filter list
+    std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
+	LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
+    for (U32 i = 0; i < filter_list.size(); i++)
+	{
+        filterbox->add(filter_list[i]);
+    }
+
 	return LLPanel::postBuild();
 }
 
@@ -398,33 +409,18 @@ void LLFacebookPhotoPanel::clearAndClose()
 void LLFacebookPhotoPanel::updateControls()
 {
 	LLSnapshotLivePreview* previewp = getPreviewView();
-	BOOL got_bytes = previewp && previewp->getDataSize() > 0;
 	BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
-	LLSnapshotLivePreview::ESnapshotType shot_type = (previewp ? previewp->getSnapshotType() : LLSnapshotLivePreview::SNAPSHOT_POSTCARD);
-
+    
 	// *TODO: Separate maximum size for Web images from postcards
 	lldebugs << "Is snapshot up-to-date? " << got_snap << llendl;
-
-	LLLocale locale(LLLocale::USER_LOCALE);
-	std::string bytes_string;
-	if (got_snap)
-	{
-		LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 );
-	}
-
-	//getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown")); <---uses localized string
-	getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : "unknown");
-	getChild<LLUICtrl>("file_size_label")->setColor(
-		shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD 
-		&& got_bytes
-		&& previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" ));
-
+    
 	updateResolution(FALSE);
 }
 
 void LLFacebookPhotoPanel::updateResolution(BOOL do_update)
 {
 	LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox);
+	LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
 
 	std::string sdstring = combobox->getSelectedValue();
 	LLSD sdres;
@@ -434,6 +430,8 @@ void LLFacebookPhotoPanel::updateResolution(BOOL do_update)
 	S32 width = sdres[0];
 	S32 height = sdres[1];
 
+    const std::string& filter_name = filterbox->getSimple();
+
 	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
 	if (previewp && combobox->getCurrentIndex() >= 0)
 	{
@@ -470,6 +468,17 @@ void LLFacebookPhotoPanel::updateResolution(BOOL do_update)
 				updateControls();
 			}
 		}
+        // Get the old filter, compare to the current one "filter_name" and set if changed
+        std::string original_filter = previewp->getFilter();
+		if (original_filter != filter_name)
+		{
+            previewp->setFilter(filter_name);
+			if (do_update)
+			{
+                previewp->updateSnapshot(FALSE, TRUE);
+				updateControls();
+			}
+		}
 	}
 }
 
diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h
index 0776f24034..04d9971332 100644
--- a/indra/newview/llfloaterfacebook.h
+++ b/indra/newview/llfloaterfacebook.h
@@ -81,6 +81,7 @@ private:
 
 	LLUICtrl * mSnapshotPanel;
 	LLUICtrl * mResolutionComboBox;
+	LLUICtrl * mFilterComboBox;
 	LLUICtrl * mRefreshBtn;
 	LLUICtrl * mWorkingLabel;
 	LLUICtrl * mThumbnailPlaceholder;
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index 5e0f652264..0b20b77c19 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -36,6 +36,7 @@
 #include "lltwitterconnect.h"
 #include "llfloaterreg.h"
 #include "lliconctrl.h"
+#include "llimagefiltersmanager.h"
 #include "llresmgr.h"		// LLLocale
 #include "llsdserialize.h"
 #include "llloadingindicator.h"
@@ -91,6 +92,8 @@ BOOL LLTwitterPhotoPanel::postBuild()
 	mSnapshotPanel = getChild<LLUICtrl>("snapshot_panel");
 	mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
 	mResolutionComboBox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::updateResolution, this, TRUE));
+	mFilterComboBox = getChild<LLUICtrl>("filters_combobox");
+	mFilterComboBox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::updateResolution, this, TRUE));
 	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
     mWorkingLabel = getChild<LLUICtrl>("working_lbl");
 	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
@@ -103,6 +106,14 @@ BOOL LLTwitterPhotoPanel::postBuild()
 	mPostButton = getChild<LLUICtrl>("post_photo_btn");
 	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
 
+	// Update filter list
+    std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
+	LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
+    for (U32 i = 0; i < filter_list.size(); i++)
+	{
+        filterbox->add(filter_list[i]);
+    }
+
 	return LLPanel::postBuild();
 }
 
@@ -356,33 +367,18 @@ void LLTwitterPhotoPanel::updateStatusTextLength(BOOL restore_old_status_text)
 void LLTwitterPhotoPanel::updateControls()
 {
 	LLSnapshotLivePreview* previewp = getPreviewView();
-	BOOL got_bytes = previewp && previewp->getDataSize() > 0;
 	BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
-	LLSnapshotLivePreview::ESnapshotType shot_type = (previewp ? previewp->getSnapshotType() : LLSnapshotLivePreview::SNAPSHOT_POSTCARD);
-
+    
 	// *TODO: Separate maximum size for Web images from postcards
 	lldebugs << "Is snapshot up-to-date? " << got_snap << llendl;
-
-	LLLocale locale(LLLocale::USER_LOCALE);
-	std::string bytes_string;
-	if (got_snap)
-	{
-		LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 );
-	}
-
-	//getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : getString("unknown")); <---uses localized string
-	getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : "unknown");
-	getChild<LLUICtrl>("file_size_label")->setColor(
-		shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD 
-		&& got_bytes
-		&& previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" ));
-
+    
 	updateResolution(FALSE);
 }
 
 void LLTwitterPhotoPanel::updateResolution(BOOL do_update)
 {
 	LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox);
+	LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
 
 	std::string sdstring = combobox->getSelectedValue();
 	LLSD sdres;
@@ -392,6 +388,8 @@ void LLTwitterPhotoPanel::updateResolution(BOOL do_update)
 	S32 width = sdres[0];
 	S32 height = sdres[1];
 
+    const std::string& filter_name = filterbox->getSimple();
+
 	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
 	if (previewp && combobox->getCurrentIndex() >= 0)
 	{
@@ -424,6 +422,17 @@ void LLTwitterPhotoPanel::updateResolution(BOOL do_update)
 				updateControls();
 			}
 		}
+        // Get the old filter, compare to the current one "filter_name" and set if changed
+        std::string original_filter = previewp->getFilter();
+		if (original_filter != filter_name)
+		{
+            previewp->setFilter(filter_name);
+			if (do_update)
+			{
+                previewp->updateSnapshot(FALSE, TRUE);
+				updateControls();
+			}
+		}
 	}
 }
 
diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h
index f267f76694..e62eda1a0e 100644
--- a/indra/newview/llfloatertwitter.h
+++ b/indra/newview/llfloatertwitter.h
@@ -66,6 +66,7 @@ private:
 
 	LLUICtrl * mSnapshotPanel;
 	LLUICtrl * mResolutionComboBox;
+	LLUICtrl * mFilterComboBox;
 	LLUICtrl * mRefreshBtn;
 	LLUICtrl * mWorkingLabel;
 	LLUICtrl * mThumbnailPlaceholder;
diff --git a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
index 2d46665bae..0a90d000bd 100644
--- a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
@@ -44,19 +44,20 @@
                name="1200x630"
                value="[i1200,i630]" />
             </combo_box>
-            <text
-             follows="left|top"
-             font="SansSerifSmall"
-             height="14"
-             left="208"
-             length="1"
-             halign="right"
-             name="file_size_label"
-             top="9"
-             type="string"
-             width="50">
-              [SIZE] KB
-            </text>
+            <combo_box
+                control_name="SocialPhotoFilters"
+                follows="right|top"
+                name="filters_combobox"
+                tool_tip="Image filters"
+                top="6"
+                left="165"
+                height="21"
+                width="135">
+                <combo_box.item
+                label="No Filter"
+                name="NoFilter"
+                value="NoFilter" />
+            </combo_box>
             <panel
                 height="150"
                 width="250"
diff --git a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
index 14268c1bcf..e044dbdf55 100644
--- a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
@@ -96,19 +96,20 @@
                name="1024x768"
                value="[i1024,i768]" />
             </combo_box>
-            <text
-             follows="left|top"
-             font="SansSerifSmall"
-             height="14"
-             left="208"
-             length="1"
-             halign="right"
-             name="file_size_label"
-             top="9"
-             type="string"
-             width="50">
-              [SIZE] KB
-            </text>
+              <combo_box
+                  control_name="SocialPhotoFilters"
+                  follows="right|top"
+                  name="filters_combobox"
+                  tool_tip="Image filters"
+                  top="6"
+                  left="165"
+                  height="21"
+                  width="135">
+                  <combo_box.item
+                  label="No Filter"
+                  name="NoFilter"
+                  value="NoFilter" />
+              </combo_box>
             <panel
                 height="150"
                 width="250"
-- 
cgit v1.2.3


From b4405c5388d1d9f562d6450092ca55cdea4c94a3 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 28 Jan 2014 19:35:39 -0800
Subject: ACME-1282 : Prevent rendering of UI in SL Share snapshots

---
 indra/newview/llfloaterfacebook.cpp     | 1 +
 indra/newview/llfloaterflickr.cpp       | 1 +
 indra/newview/llfloatertwitter.cpp      | 1 +
 indra/newview/llsnapshotlivepreview.cpp | 7 ++++---
 indra/newview/llsnapshotlivepreview.h   | 2 ++
 5 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index f86b6d580a..2b3afb7b18 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -313,6 +313,7 @@ void LLFacebookPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
 			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
 			previewp->setSnapshotQuality(mQuality, false);
             previewp->setThumbnailSubsampled(TRUE);     // We want the preview to reflect the *saved* image
+            previewp->setAllowRenderUI(FALSE);          // We do not want the rendered UI in our snapshots
 			previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
 
 			updateControls();
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 2dc62dcda8..35d891fb6d 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -203,6 +203,7 @@ void LLFlickrPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
 			previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
 			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
             previewp->setThumbnailSubsampled(TRUE);     // We want the preview to reflect the *saved* image
+            previewp->setAllowRenderUI(FALSE);          // We do not want the rendered UI in our snapshots
 			previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
 
 			updateControls();
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index 0b20b77c19..09821a2593 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -204,6 +204,7 @@ void LLTwitterPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
 			previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
 			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
             previewp->setThumbnailSubsampled(TRUE);     // We want the preview to reflect the *saved* image
+            previewp->setAllowRenderUI(FALSE);          // We do not want the rendered UI in our snapshots
 			previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
 
 			updateControls();
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 0d1562b6d4..9e982459ba 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -93,7 +93,8 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param
 	mCameraRot(LLViewerCamera::getInstance()->getQuaternion()),
 	mSnapshotActive(FALSE),
 	mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR),
-    mFilterName("")
+    mFilterName(""),
+    mAllowRenderUI(TRUE)
 {
 	setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality"));
 	mSnapshotDelayTimer.setTimerExpirySec(0.0f);
@@ -565,7 +566,7 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
         // The thumbnail is a screen view with screen grab positioning preview
         if(!gViewerWindow->thumbnailSnapshot(raw,
                                          mThumbnailWidth, mThumbnailHeight,
-                                         gSavedSettings.getBOOL("RenderUIInSnapshot"),
+                                         mAllowRenderUI && gSavedSettings.getBOOL("RenderUIInSnapshot"),
                                          FALSE,
                                          mSnapshotBufferType) )
         {
@@ -662,7 +663,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
                 previewp->getHeight(),
                 previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"),
                 previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE,
-                gSavedSettings.getBOOL("RenderUIInSnapshot"),
+                previewp->mAllowRenderUI && gSavedSettings.getBOOL("RenderUIInSnapshot"),
                 FALSE,
                 previewp->mSnapshotBufferType,
                 previewp->getMaxImageSize()))
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index 10f20e7fe8..b1efbd1be8 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -99,6 +99,7 @@ public:
 	void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat format);
 	bool setSnapshotQuality(S32 quality, bool set_by_user = true);
 	void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
+    void setAllowRenderUI(BOOL allow) { mAllowRenderUI = allow; }
     void setFilter(std::string filter_name) { mFilterName = filter_name; }
     std::string  getFilter() const { return mFilterName; }
 	void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f);
@@ -146,6 +147,7 @@ private:
 	LLPointer<LLImageRaw>		mPreviewImage;
 	LLPointer<LLImageRaw>		mPreviewImageEncoded;
 	LLPointer<LLImageFormatted>	mFormattedImage;
+    BOOL                        mAllowRenderUI;
 	LLFrameTimer				mSnapshotDelayTimer;
 	S32							mShineCountdown;
 	LLFrameTimer				mShineAnimTimer;
-- 
cgit v1.2.3


From c7c755b82e736050a514792a4c4bbdee9bf981d3 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 29 Jan 2014 14:21:43 -0800
Subject: ACME-1272, ACME-1292 : Disable filter drop down when necessary

---
 indra/newview/llfloaterfacebook.cpp | 1 +
 indra/newview/llfloaterflickr.cpp   | 1 +
 indra/newview/llfloatertwitter.cpp  | 6 ++++--
 3 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 2b3afb7b18..df1643ee22 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -238,6 +238,7 @@ void LLFacebookPhotoPanel::draw()
     mCancelButton->setEnabled(no_ongoing_connection);
     mCaptionTextBox->setEnabled(no_ongoing_connection);
     mResolutionComboBox->setEnabled(no_ongoing_connection);
+    mFilterComboBox->setEnabled(no_ongoing_connection);
     mRefreshBtn->setEnabled(no_ongoing_connection);
     mLocationCheckbox->setEnabled(no_ongoing_connection);
     
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 35d891fb6d..244a34c782 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -130,6 +130,7 @@ void LLFlickrPhotoPanel::draw()
     mTagsTextBox->setEnabled(no_ongoing_connection);
     mRatingComboBox->setEnabled(no_ongoing_connection);
     mResolutionComboBox->setEnabled(no_ongoing_connection);
+    mFilterComboBox->setEnabled(no_ongoing_connection);
     mRefreshBtn->setEnabled(no_ongoing_connection);
     mLocationCheckbox->setEnabled(no_ongoing_connection);
     
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index 09821a2593..2c327b4cd3 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -123,10 +123,12 @@ void LLTwitterPhotoPanel::draw()
 
     // Enable interaction only if no transaction with the service is on-going (prevent duplicated posts)
     bool no_ongoing_connection = !(LLTwitterConnect::instance().isTransactionOngoing());
+    bool photo_checked = mPhotoCheckbox->getValue().asBoolean();
     mCancelButton->setEnabled(no_ongoing_connection);
     mStatusTextBox->setEnabled(no_ongoing_connection);
-    mResolutionComboBox->setEnabled(no_ongoing_connection && mPhotoCheckbox->getValue().asBoolean());
-    mRefreshBtn->setEnabled(no_ongoing_connection && mPhotoCheckbox->getValue().asBoolean());
+    mResolutionComboBox->setEnabled(no_ongoing_connection && photo_checked);
+    mFilterComboBox->setEnabled(no_ongoing_connection && photo_checked);
+    mRefreshBtn->setEnabled(no_ongoing_connection && photo_checked);
     mLocationCheckbox->setEnabled(no_ongoing_connection);
     mPhotoCheckbox->setEnabled(no_ongoing_connection);
 
-- 
cgit v1.2.3


From e42a372592a9b6c996d989a7e38c62761f73908a Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 29 Jan 2014 22:41:27 -0800
Subject: ACME : Add filters to Snapshot Advanced panel for demo

---
 indra/newview/llfloatersnapshot.cpp                | 30 ++++++++++++++++++++--
 .../skins/default/xui/en/floater_snapshot.xml      | 14 ++++++++++
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 27a9e3da44..e3d67ee658 100755
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -34,6 +34,7 @@
 #include "llfloaterfacebook.h"
 #include "llfloaterflickr.h"
 #include "llfloatertwitter.h"
+#include "llimagefiltersmanager.h"
 #include "llcheckboxctrl.h"
 #include "llcombobox.h"
 #include "llpostcard.h"
@@ -94,6 +95,7 @@ public:
 	}
 	static void onClickNewSnapshot(void* data);
 	static void onClickAutoSnap(LLUICtrl *ctrl, void* data);
+	static void onClickFilter(LLUICtrl *ctrl, void* data);
 	//static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data);
 	static void onClickMore(void* data) ;
 	static void onClickUICheck(LLUICtrl *ctrl, void* data);
@@ -470,12 +472,15 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
 	  default:
 		break;
 	}
-
-	if (previewp)
+    
+    if (previewp)
 	{
 		previewp->setSnapshotType(shot_type);
 		previewp->setSnapshotFormat(shot_format);
 		previewp->setSnapshotBufferType(layer_type);
+        // Filters
+        const std::string& filter_name = floater->getChild<LLComboBox>("filters_combobox")->getSimple();
+        previewp->setFilter(filter_name);
 	}
 
 	LLPanelSnapshot* current_panel = Impl::getActivePanel(floater);
@@ -564,6 +569,17 @@ void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data)
 	}
 }
 
+// static
+void LLFloaterSnapshot::Impl::onClickFilter(LLUICtrl *ctrl, void* data)
+{
+	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
+	if (view)
+	{
+		checkAutoSnapshot(getPreviewView(view));
+		updateControls(view);
+	}
+}
+
 void LLFloaterSnapshot::Impl::onClickMore(void* data)
 {
 	BOOL visible = gSavedSettings.getBOOL("AdvanceSnapshot");
@@ -1061,6 +1077,16 @@ BOOL LLFloaterSnapshot::postBuild()
 
 	getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot"));
 	childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this);
+    
+	// Update filter list
+    std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
+	LLComboBox* filterbox = getChild<LLComboBox>("filters_combobox");
+    for (U32 i = 0; i < filter_list.size(); i++)
+	{
+        filterbox->add(filter_list[i]);
+    }
+	childSetCommitCallback("filters_combobox", Impl::onClickFilter, this);
+    
 	
 	LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUploadFinished, _1));
 	LLPostCard::setPostResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSendingPostcardFinished, _1));
diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml
index 019ddad33c..705225b839 100755
--- a/indra/newview/skins/default/xui/en/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml
@@ -381,5 +381,19 @@
          top_pad="8"
          width="180"
          name="auto_snapshot_check" />
+        <combo_box
+            control_name="PhotoFilters"
+            follows="left|right|top"
+            name="filters_combobox"
+            tool_tip="Image filters"
+            top_pad="8"
+            left="30"
+            height="21"
+            width="135">
+            <combo_box.item
+            label="No Filter"
+            name="NoFilter"
+            value="NoFilter" />
+        </combo_box>
     </panel>
 </floater>
-- 
cgit v1.2.3


From e970fa7f1ce9190b8a26e72bebbcceed04fb7494 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Thu, 30 Jan 2014 18:53:05 -0800
Subject: ACME-1293 : Use notification to signal from the snapshot panel to its
 container rather than grabbing global instances, use unique control_name for
 widgets, fix Post button visibility on Twitter

---
 indra/newview/llfloaterfacebook.cpp                | 61 ++++++++++-----------
 indra/newview/llfloaterfacebook.h                  |  4 +-
 indra/newview/llfloaterflickr.cpp                  | 61 ++++++++++-----------
 indra/newview/llfloaterflickr.h                    |  6 +-
 indra/newview/llfloatersnapshot.cpp                | 64 +++++++++-------------
 indra/newview/llfloatersnapshot.h                  |  2 -
 indra/newview/llfloatertwitter.cpp                 | 63 ++++++++++-----------
 indra/newview/llfloatertwitter.h                   |  6 +-
 indra/newview/llsnapshotlivepreview.cpp            | 24 ++++----
 indra/newview/llsnapshotlivepreview.h              |  4 ++
 .../skins/default/xui/en/panel_facebook_photo.xml  |  4 +-
 .../skins/default/xui/en/panel_flickr_photo.xml    |  4 +-
 .../skins/default/xui/en/panel_twitter_photo.xml   |  4 +-
 13 files changed, 144 insertions(+), 163 deletions(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index df1643ee22..4e25f4e27d 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -229,6 +229,34 @@ BOOL LLFacebookPhotoPanel::postBuild()
 	return LLPanel::postBuild();
 }
 
+// virtual
+S32 LLFacebookPhotoPanel::notify(const LLSD& info)
+{
+	if (info.has("snapshot-updating"))
+	{
+        // Disable the Post button and whatever else while the snapshot is not updated
+        // updateControls();
+		return 1;
+	}
+    
+	if (info.has("snapshot-updated"))
+	{
+        // Enable the send/post/save buttons.
+        updateControls();
+        
+		// The refresh button is initially hidden. We show it after the first update,
+		// i.e. after snapshot is taken
+		LLUICtrl * refresh_button = getRefreshBtn();
+		if (!refresh_button->getVisible())
+		{
+			refresh_button->setVisible(true);
+		}
+		return 1;
+	}
+    
+	return 0;
+}
+
 void LLFacebookPhotoPanel::draw()
 { 
 	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
@@ -310,6 +338,7 @@ void LLFacebookPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
 			mPreviewHandle = previewp->getHandle();	
             mQuality = MAX_QUALITY;
 
+            previewp->setContainer(this);
 			previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
 			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
 			previewp->setSnapshotQuality(mQuality, false);
@@ -861,38 +890,6 @@ void LLFloaterFacebook::showPhotoPanel()
 	parent->selectTabPanel(mFacebookPhotoPanel);
 }
 
-// static
-void LLFloaterFacebook::preUpdate()
-{
-	LLFloaterFacebook* instance = LLFloaterReg::findTypedInstance<LLFloaterFacebook>("facebook");
-	if (instance)
-	{
-		//Will set file size text to 'unknown'
-		instance->mFacebookPhotoPanel->updateControls();
-	}
-}
-
-// static
-void LLFloaterFacebook::postUpdate()
-{
-	LLFloaterFacebook* instance = LLFloaterReg::findTypedInstance<LLFloaterFacebook>("facebook");
-	if (instance)
-	{
-		//Will set the file size text
-		instance->mFacebookPhotoPanel->updateControls();
-
-		// The refresh button is initially hidden. We show it after the first update,
-		// i.e. after snapshot is taken
-		LLUICtrl * refresh_button = instance->mFacebookPhotoPanel->getRefreshBtn();
-
-		if (!refresh_button->getVisible())
-		{
-			refresh_button->setVisible(true);
-		}
-		
-	}
-}
-
 void LLFloaterFacebook::draw()
 {
     if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator)
diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h
index 04d9971332..4361dfa628 100644
--- a/indra/newview/llfloaterfacebook.h
+++ b/indra/newview/llfloaterfacebook.h
@@ -66,6 +66,7 @@ public:
 	void onVisibilityChange(const LLSD& new_visibility);
 	void onClickNewSnapshot();
 	void onSend();
+	S32 notify(const LLSD& info);
 	bool onFacebookConnectStateChange(const LLSD& data);
 
 	void sendPhoto();
@@ -156,9 +157,6 @@ public:
 	
 	void showPhotoPanel();
 
-	static void preUpdate();
-	static void postUpdate();
-
 private:
 	LLFacebookPhotoPanel* mFacebookPhotoPanel;
     LLTextBox* mStatusErrorText;
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 244a34c782..2c8ec56941 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -118,6 +118,34 @@ BOOL LLFlickrPhotoPanel::postBuild()
 	return LLPanel::postBuild();
 }
 
+// virtual
+S32 LLFlickrPhotoPanel::notify(const LLSD& info)
+{
+	if (info.has("snapshot-updating"))
+	{
+        // Disable the Post button and whatever else while the snapshot is not updated
+        // updateControls();
+		return 1;
+	}
+    
+	if (info.has("snapshot-updated"))
+	{
+        // Enable the send/post/save buttons.
+        updateControls();
+        
+		// The refresh button is initially hidden. We show it after the first update,
+		// i.e. after snapshot is taken
+		LLUICtrl * refresh_button = getRefreshBtn();
+		if (!refresh_button->getVisible())
+		{
+			refresh_button->setVisible(true);
+		}
+		return 1;
+	}
+    
+	return 0;
+}
+
 void LLFlickrPhotoPanel::draw()
 { 
 	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
@@ -201,6 +229,7 @@ void LLFlickrPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
 			LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
 			mPreviewHandle = previewp->getHandle();	
 
+            previewp->setContainer(this);
 			previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
 			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
             previewp->setThumbnailSubsampled(TRUE);     // We want the preview to reflect the *saved* image
@@ -605,38 +634,6 @@ void LLFloaterFlickr::showPhotoPanel()
 	parent->selectTabPanel(mFlickrPhotoPanel);
 }
 
-// static
-void LLFloaterFlickr::preUpdate()
-{
-	LLFloaterFlickr* instance = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr");
-	if (instance)
-	{
-		//Will set file size text to 'unknown'
-		instance->mFlickrPhotoPanel->updateControls();
-	}
-}
-
-// static
-void LLFloaterFlickr::postUpdate()
-{
-	LLFloaterFlickr* instance = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr");
-	if (instance)
-	{
-		//Will set the file size text
-		instance->mFlickrPhotoPanel->updateControls();
-
-		// The refresh button is initially hidden. We show it after the first update,
-		// i.e. after snapshot is taken
-		LLUICtrl * refresh_button = instance->mFlickrPhotoPanel->getRefreshBtn();
-
-		if (!refresh_button->getVisible())
-		{
-			refresh_button->setVisible(true);
-		}
-		
-	}
-}
-
 void LLFloaterFlickr::draw()
 {
     if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator)
diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h
index 1d9e649899..319ab1278f 100644
--- a/indra/newview/llfloaterflickr.h
+++ b/indra/newview/llfloaterflickr.h
@@ -42,6 +42,7 @@ public:
 	~LLFlickrPhotoPanel();
 
 	BOOL postBuild();
+	S32 notify(const LLSD& info);
 	void draw();
 
 	LLSnapshotLivePreview* getPreviewView();
@@ -73,7 +74,7 @@ private:
 	LLUICtrl * mTagsTextBox;
 	LLUICtrl * mRatingComboBox;
 	LLUICtrl * mPostButton;
-	LLUICtrl* mCancelButton;
+	LLUICtrl * mCancelButton;
 };
 
 class LLFlickrAccountPanel : public LLPanel
@@ -114,9 +115,6 @@ public:
 	
 	void showPhotoPanel();
 
-	static void preUpdate();
-	static void postUpdate();
-
 private:
 	LLFlickrPhotoPanel* mFlickrPhotoPanel;
     LLTextBox* mStatusErrorText;
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 27a9e3da44..3a176b82d2 100755
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -1091,6 +1091,7 @@ BOOL LLFloaterSnapshot::postBuild()
 	getChild<LLComboBox>("local_format_combo")->selectNthItem(0);
 
 	impl.mPreviewHandle = previewp->getHandle();
+    previewp->setContainer(this);
 	impl.updateControls(this);
 	impl.updateLayout(this);
 	
@@ -1255,6 +1256,32 @@ S32 LLFloaterSnapshot::notify(const LLSD& info)
 		impl.setStatus(Impl::STATUS_FINISHED, data["ok"].asBoolean(), data["msg"].asString());
 		return 1;
 	}
+    
+	if (info.has("snapshot-updating"))
+	{
+        // Disable the send/post/save buttons until snapshot is ready.
+        impl.updateControls(this);
+        // Force hiding the "Refresh to save" hint because we know we've just started refresh.
+        impl.setNeedRefresh(this, false);
+		return 1;
+	}
+
+	if (info.has("snapshot-updated"))
+	{
+        // Enable the send/post/save buttons.
+        impl.updateControls(this);
+        // We've just done refresh.
+        impl.setNeedRefresh(this, false);
+            
+        // The refresh button is initially hidden. We show it after the first update,
+        // i.e. when preview appears.
+        if (!mRefreshBtn->getVisible())
+        {
+            mRefreshBtn->setVisible(true);
+        }
+		return 1;
+	}    
+    
 	return 0;
 }
 
@@ -1333,43 +1360,6 @@ BOOL LLFloaterSnapshot::saveLocal()
 	return previewp->saveLocal();
 }
 
-// static
-void LLFloaterSnapshot::preUpdate()
-{
-	// FIXME: duplicated code
-	LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot");
-	if (instance)
-	{
-		// Disable the send/post/save buttons until snapshot is ready.
-		Impl::updateControls(instance);
-
-		// Force hiding the "Refresh to save" hint because we know we've just started refresh.
-		Impl::setNeedRefresh(instance, false);
-	}
-}
-
-// static
-void LLFloaterSnapshot::postUpdate()
-{
-	// FIXME: duplicated code
-	LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot");
-	if (instance)
-	{
-		// Enable the send/post/save buttons.
-		Impl::updateControls(instance);
-
-		// We've just done refresh.
-		Impl::setNeedRefresh(instance, false);
-
-		// The refresh button is initially hidden. We show it after the first update,
-		// i.e. when preview appears.
-		if (!instance->mRefreshBtn->getVisible())
-		{
-			instance->mRefreshBtn->setVisible(true);
-		}
-	}
-}
-
 // static
 void LLFloaterSnapshot::postSave()
 {
diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h
index 82af8c7a9d..3a279c194d 100755
--- a/indra/newview/llfloatersnapshot.h
+++ b/indra/newview/llfloatersnapshot.h
@@ -58,8 +58,6 @@ public:
 	static LLFloaterSnapshot* getInstance();
 	static void saveTexture();
 	static BOOL saveLocal();
-	static void preUpdate();
-	static void postUpdate();
 	static void postSave();
 	static void postPanelSwitch();
 	static LLPointer<LLImageFormatted> getImageData();
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index 2c327b4cd3..ffe2609972 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -117,6 +117,34 @@ BOOL LLTwitterPhotoPanel::postBuild()
 	return LLPanel::postBuild();
 }
 
+// virtual
+S32 LLTwitterPhotoPanel::notify(const LLSD& info)
+{
+	if (info.has("snapshot-updating"))
+	{
+        // Disable the Post button and whatever else while the snapshot is not updated
+        // updateControls();
+		return 1;
+	}
+    
+	if (info.has("snapshot-updated"))
+	{
+        // Enable the send/post/save buttons.
+        updateControls();
+        
+		// The refresh button is initially hidden. We show it after the first update,
+		// i.e. after snapshot is taken
+		LLUICtrl * refresh_button = getRefreshBtn();
+		if (!refresh_button->getVisible())
+		{
+			refresh_button->setVisible(true);
+		}
+		return 1;
+	}
+    
+	return 0;
+}
+
 void LLTwitterPhotoPanel::draw()
 { 
 	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
@@ -169,7 +197,7 @@ void LLTwitterPhotoPanel::draw()
     mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate()));
     
     // Enable Post if we have a preview to send and no on going connection being processed
-    mPostButton->setEnabled(no_ongoing_connection && ((add_photo && previewp && previewp->getSnapshotUpToDate()) || add_location || !mStatusTextBox->getValue().asString().empty()));
+    mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()) && (add_photo || add_location || !mStatusTextBox->getValue().asString().empty()));
     
     // Draw the rest of the panel on top of it
 	LLPanel::draw();
@@ -203,6 +231,7 @@ void LLTwitterPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
 			LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
 			mPreviewHandle = previewp->getHandle();
 
+            previewp->setContainer(this);
 			previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
 			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
             previewp->setThumbnailSubsampled(TRUE);     // We want the preview to reflect the *saved* image
@@ -666,38 +695,6 @@ void LLFloaterTwitter::showPhotoPanel()
 	parent->selectTabPanel(mTwitterPhotoPanel);
 }
 
-// static
-void LLFloaterTwitter::preUpdate()
-{
-	LLFloaterTwitter* instance = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter");
-	if (instance)
-	{
-		//Will set file size text to 'unknown'
-		instance->mTwitterPhotoPanel->updateControls();
-	}
-}
-
-// static
-void LLFloaterTwitter::postUpdate()
-{
-	LLFloaterTwitter* instance = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter");
-	if (instance)
-	{
-		//Will set the file size text
-		instance->mTwitterPhotoPanel->updateControls();
-
-		// The refresh button is initially hidden. We show it after the first update,
-		// i.e. after snapshot is taken
-		LLUICtrl * refresh_button = instance->mTwitterPhotoPanel->getRefreshBtn();
-
-		if (!refresh_button->getVisible())
-		{
-			refresh_button->setVisible(true);
-		}
-		
-	}
-}
-
 void LLFloaterTwitter::draw()
 {
     if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator)
diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h
index e62eda1a0e..bb88557ad8 100644
--- a/indra/newview/llfloatertwitter.h
+++ b/indra/newview/llfloatertwitter.h
@@ -50,6 +50,7 @@ public:
 	void onAddPhotoToggled();
 	void onClickNewSnapshot();
 	void onSend();
+	S32 notify(const LLSD& info);
 	bool onTwitterConnectStateChange(const LLSD& data);
 
 	void sendPhoto();
@@ -75,7 +76,7 @@ private:
 	LLUICtrl * mLocationCheckbox;
 	LLUICtrl * mPhotoCheckbox;
 	LLUICtrl * mPostButton;
-	LLUICtrl* mCancelButton;
+	LLUICtrl * mCancelButton;
 
 	std::string mOldStatusText;
 };
@@ -118,9 +119,6 @@ public:
 
 	void showPhotoPanel();
 
-	static void preUpdate();
-	static void postUpdate();
-
 private:
 	LLTwitterPhotoPanel* mTwitterPhotoPanel;
     LLTextBox* mStatusErrorText;
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 9e982459ba..60ef0fddd4 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -94,7 +94,8 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param
 	mSnapshotActive(FALSE),
 	mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR),
     mFilterName(""),
-    mAllowRenderUI(TRUE)
+    mAllowRenderUI(TRUE),
+    mViewContainer(NULL)
 {
 	setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality"));
 	mSnapshotDelayTimer.setTimerExpirySec(0.0f);
@@ -189,13 +190,14 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail
 
         // Stop shining animation.
         mShineAnimTimer.stop();
-
 		mSnapshotDelayTimer.start();
 		mSnapshotDelayTimer.setTimerExpirySec(delay);
-		LLFloaterSnapshot::preUpdate();
-		LLFloaterFacebook::preUpdate();
-		LLFloaterFlickr::preUpdate();
-		LLFloaterTwitter::preUpdate();
+        
+        // Tell the floater container that the snapshot is in the process of updating itself
+        if (mViewContainer)
+        {
+            mViewContainer->notify(LLSD().with("snapshot-updating", true));
+        }
 	}
 
 	// Update thumbnail if requested.
@@ -731,10 +733,12 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 	{
 		previewp->generateThumbnailImage() ;
 	}
-	LLFloaterSnapshot::postUpdate();
-	LLFloaterFacebook::postUpdate();
-	LLFloaterFlickr::postUpdate();
-	LLFloaterTwitter::postUpdate();
+    
+    // Tell the floater container that the snapshot is updated now
+    if (previewp->mViewContainer)
+    {
+        previewp->mViewContainer->notify(LLSD().with("snapshot-updated", true));
+    }
 
 	return TRUE;
 }
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index b1efbd1be8..801c588060 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -61,6 +61,8 @@ public:
 	LLSnapshotLivePreview(const LLSnapshotLivePreview::Params& p);
 	~LLSnapshotLivePreview();
 
+    void setContainer(LLView* container) { mViewContainer = container; }
+
 	/*virtual*/ void draw();
 	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
 
@@ -124,6 +126,8 @@ public:
 	void regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z);
 
 private:
+    LLView*                     mViewContainer;
+    
 	LLColor4					mColor;
 	LLPointer<LLViewerTexture>	mViewerImage[2]; //used to represent the scene when the frame is frozen.
 	LLRect						mImageRect[2];
diff --git a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
index 0a90d000bd..0cde43a20c 100644
--- a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
@@ -15,7 +15,7 @@
          name="snapshot_panel"
          height="367">
             <combo_box
-             control_name="SocialPhotoResolution"
+             control_name="FacebookPhotoResolution"
              follows="left|top"
              top="6"
              left="9"
@@ -45,7 +45,7 @@
                value="[i1200,i630]" />
             </combo_box>
             <combo_box
-                control_name="SocialPhotoFilters"
+                control_name="FacebookPhotoFilters"
                 follows="right|top"
                 name="filters_combobox"
                 tool_tip="Image filters"
diff --git a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
index 47ddecdf38..01116c6c4c 100644
--- a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
@@ -15,7 +15,7 @@
          name="snapshot_panel"
          height="507">
             <combo_box
-             control_name="SocialPhotoResolution"
+             control_name="FlickrPhotoResolution"
              follows="left|top"
              top="6"
              left="9"
@@ -41,7 +41,7 @@
                value="[i1024,i768]" />
             </combo_box>
             <combo_box
-               control_name="SocialPhotoFilters"
+               control_name="FlickrPhotoFilters"
                follows="right|top"
                name="filters_combobox"
                tool_tip="Image filters"
diff --git a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
index e044dbdf55..bcec09ebab 100644
--- a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
@@ -71,7 +71,7 @@
            name="snapshot_panel"
            height="227">
             <combo_box
-             control_name="SocialPhotoResolution"
+             control_name="TwitterPhotoResolution"
              follows="left|top"
              top="6"
              left="9"
@@ -97,7 +97,7 @@
                value="[i1024,i768]" />
             </combo_box>
               <combo_box
-                  control_name="SocialPhotoFilters"
+                  control_name="TwitterPhotoFilters"
                   follows="right|top"
                   name="filters_combobox"
                   tool_tip="Image filters"
-- 
cgit v1.2.3


From 009449126a350f60dd90da9879247ceacb99936f Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Fri, 31 Jan 2014 12:08:23 -0800
Subject: ACME-1296 : Remove Filters from Advanced Snapshot panel

---
 indra/newview/llfloatersnapshot.cpp                    | 18 +++++++++---------
 .../newview/skins/default/xui/en/floater_snapshot.xml  | 14 ++++++++++++++
 2 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 1a569e41cd..1d52ac5a69 100755
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -479,8 +479,8 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
 		previewp->setSnapshotFormat(shot_format);
 		previewp->setSnapshotBufferType(layer_type);
         // Filters
-        const std::string& filter_name = floater->getChild<LLComboBox>("filters_combobox")->getSimple();
-        previewp->setFilter(filter_name);
+        //const std::string& filter_name = floater->getChild<LLComboBox>("filters_combobox")->getSimple();
+        //previewp->setFilter(filter_name);
 	}
 
 	LLPanelSnapshot* current_panel = Impl::getActivePanel(floater);
@@ -1079,13 +1079,13 @@ BOOL LLFloaterSnapshot::postBuild()
 	childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this);
     
 	// Update filter list
-    std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
-	LLComboBox* filterbox = getChild<LLComboBox>("filters_combobox");
-    for (U32 i = 0; i < filter_list.size(); i++)
-	{
-        filterbox->add(filter_list[i]);
-    }
-	childSetCommitCallback("filters_combobox", Impl::onClickFilter, this);
+    //std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
+	//LLComboBox* filterbox = getChild<LLComboBox>("filters_combobox");
+    //for (U32 i = 0; i < filter_list.size(); i++)
+	//{
+    //    filterbox->add(filter_list[i]);
+    //}
+	//childSetCommitCallback("filters_combobox", Impl::onClickFilter, this);
     
 	
 	LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUploadFinished, _1));
diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml
index 705225b839..5e3c7d4e3d 100755
--- a/indra/newview/skins/default/xui/en/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml
@@ -381,6 +381,19 @@
          top_pad="8"
          width="180"
          name="auto_snapshot_check" />
+        <!-- If we ever want to add filters to the snapshot panel...
+        <text
+         type="string"
+         length="1"
+         follows="left|top"
+         height="13"
+         layout="topleft"
+         left="10"
+         name="layer_type_label"
+         top_pad="10"
+         width="50">
+            Filter:
+        </text>
         <combo_box
             control_name="PhotoFilters"
             follows="left|right|top"
@@ -395,5 +408,6 @@
             name="NoFilter"
             value="NoFilter" />
         </combo_box>
+         -->
     </panel>
 </floater>
-- 
cgit v1.2.3


From 9099cddb553bf9a2239bba86e6f1135bca76ed8b Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Mon, 3 Feb 2014 14:57:56 -0800
Subject: ACME-1295 : Implement an mAllowFullScreenPreview flag in snapshot

---
 indra/newview/llfloaterfacebook.cpp     | 1 +
 indra/newview/llfloaterflickr.cpp       | 1 +
 indra/newview/llfloatertwitter.cpp      | 1 +
 indra/newview/llsnapshotlivepreview.cpp | 7 ++++---
 indra/newview/llsnapshotlivepreview.h   | 2 ++
 5 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 4e25f4e27d..5e1e3ad40f 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -344,6 +344,7 @@ void LLFacebookPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
 			previewp->setSnapshotQuality(mQuality, false);
             previewp->setThumbnailSubsampled(TRUE);     // We want the preview to reflect the *saved* image
             previewp->setAllowRenderUI(FALSE);          // We do not want the rendered UI in our snapshots
+            previewp->setAllowFullScreenPreview(FALSE);  // No full screen preview in SL Share mode
 			previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
 
 			updateControls();
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 2c8ec56941..74fdb9879c 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -234,6 +234,7 @@ void LLFlickrPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
 			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
             previewp->setThumbnailSubsampled(TRUE);     // We want the preview to reflect the *saved* image
             previewp->setAllowRenderUI(FALSE);          // We do not want the rendered UI in our snapshots
+            previewp->setAllowFullScreenPreview(FALSE);  // No full screen preview in SL Share mode
 			previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
 
 			updateControls();
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index ffe2609972..08b0cb6097 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -236,6 +236,7 @@ void LLTwitterPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
 			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
             previewp->setThumbnailSubsampled(TRUE);     // We want the preview to reflect the *saved* image
             previewp->setAllowRenderUI(FALSE);          // We do not want the rendered UI in our snapshots
+            previewp->setAllowFullScreenPreview(FALSE);  // No full screen preview in SL Share mode
 			previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
 
 			updateControls();
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 60ef0fddd4..2a5bd5d8bc 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -95,6 +95,7 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param
 	mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR),
     mFilterName(""),
     mAllowRenderUI(TRUE),
+    mAllowFullScreenPreview(TRUE),
     mViewContainer(NULL)
 {
 	setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality"));
@@ -620,7 +621,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
 	// If we're in freeze-frame mode and camera has moved, update snapshot.
 	LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin();
 	LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion();
-	if (gSavedSettings.getBOOL("FreezeTime") && 
+	if (gSavedSettings.getBOOL("FreezeTime") && previewp->mAllowFullScreenPreview &&
 		(new_camera_pos != previewp->mCameraPos || dot(new_camera_rot, previewp->mCameraRot) < 0.995f))
 	{
 		previewp->mCameraPos = new_camera_pos;
@@ -678,7 +679,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
             previewp->estimateDataSize();
 
             // Full size preview is set: get the decoded image result and save it for animation
-            if (gSavedSettings.getBOOL("UseFreezeFrame"))
+            if (gSavedSettings.getBOOL("UseFreezeFrame") && previewp->mAllowFullScreenPreview)
             {
                 // Get the decoded version of the formatted image
                 previewp->getEncodedImage();
@@ -723,7 +724,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
             previewp->generateThumbnailImage(TRUE) ;
         }
         previewp->getWindow()->decBusyCount();
-        previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame")); // only show fullscreen preview when in freeze frame mode
+        previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame") && previewp->mAllowFullScreenPreview); // only show fullscreen preview when in freeze frame mode
         previewp->mSnapshotDelayTimer.stop();
         previewp->mSnapshotActive = FALSE;
         lldebugs << "done creating snapshot" << llendl;
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index 801c588060..7f3e7a080b 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -102,6 +102,7 @@ public:
 	bool setSnapshotQuality(S32 quality, bool set_by_user = true);
 	void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
     void setAllowRenderUI(BOOL allow) { mAllowRenderUI = allow; }
+    void setAllowFullScreenPreview(BOOL allow) { mAllowFullScreenPreview = allow; }
     void setFilter(std::string filter_name) { mFilterName = filter_name; }
     std::string  getFilter() const { return mFilterName; }
 	void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f);
@@ -152,6 +153,7 @@ private:
 	LLPointer<LLImageRaw>		mPreviewImageEncoded;
 	LLPointer<LLImageFormatted>	mFormattedImage;
     BOOL                        mAllowRenderUI;
+    BOOL                        mAllowFullScreenPreview;
 	LLFrameTimer				mSnapshotDelayTimer;
 	S32							mShineCountdown;
 	LLFrameTimer				mShineAnimTimer;
-- 
cgit v1.2.3


From a355659513a29f5b36207a57351797d18023966d Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Mon, 3 Feb 2014 15:55:17 -0800
Subject: ACME-1294 : Tweak the JuleVerne, Newspaper and Video filters so to be
 more legible

---
 indra/newview/app_settings/filters/JulesVerne.xml | 4 ++--
 indra/newview/app_settings/filters/Newspaper.xml  | 4 ++--
 indra/newview/app_settings/filters/Video.xml      | 6 +++---
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/indra/newview/app_settings/filters/JulesVerne.xml b/indra/newview/app_settings/filters/JulesVerne.xml
index b0d4f8e9cd..35bc657c11 100644
--- a/indra/newview/app_settings/filters/JulesVerne.xml
+++ b/indra/newview/app_settings/filters/JulesVerne.xml
@@ -14,8 +14,8 @@
             <string>stencil</string>
             <string>vignette</string>
             <string>blend</string>
-            <real>0.0</real>
             <real>1.0</real>
+            <real>0.1</real>
             <real>0.0</real>
             <real>0.0</real>
             <real>1.0</real>
@@ -24,7 +24,7 @@
         <array>
             <string>screen</string>
             <string>line</string>
-            <real>0.01</real>
+            <real>0.02</real>
             <real>0.0</real>
         </array>
     </array>
diff --git a/indra/newview/app_settings/filters/Newspaper.xml b/indra/newview/app_settings/filters/Newspaper.xml
index b02a553dfa..8441decf3b 100755
--- a/indra/newview/app_settings/filters/Newspaper.xml
+++ b/indra/newview/app_settings/filters/Newspaper.xml
@@ -14,8 +14,8 @@
             <string>stencil</string>
             <string>vignette</string>
             <string>blend</string>
-            <real>0.0</real>
             <real>1.0</real>
+            <real>0.1</real>
             <real>0.0</real>
             <real>0.0</real>
             <real>1.0</real>
@@ -24,7 +24,7 @@
         <array>
             <string>screen</string>
             <string>2Dsine</string>
-            <real>0.01</real>
+            <real>0.02</real>
             <real>0.0</real>
         </array>
     </array>
diff --git a/indra/newview/app_settings/filters/Video.xml b/indra/newview/app_settings/filters/Video.xml
index 09c4c79638..aa65536235 100755
--- a/indra/newview/app_settings/filters/Video.xml
+++ b/indra/newview/app_settings/filters/Video.xml
@@ -9,7 +9,7 @@
         </array>
         <array>
             <string>darken</string>
-            <real>0.1</real>
+            <real>0.2</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
@@ -20,12 +20,12 @@
             <string>blend</string>
             <real>0.0</real>
             <real>1.0</real>
-            <real>0.01</real>
+            <real>0.02</real>
             <real>0.0</real>
         </array>
         <array>
             <string>brighten</string>
-            <real>0.1</real>
+            <real>0.2</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
-- 
cgit v1.2.3


From cfde9440c9202e6f2b313761067d2884cff98c05 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Thu, 6 Feb 2014 00:17:09 +0000
Subject: Switched Flickr upload to PNG for ACME-1302

---
 indra/newview/llfloaterflickr.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 74fdb9879c..ca1022d09d 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -231,7 +231,7 @@ void LLFlickrPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
 
             previewp->setContainer(this);
 			previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
-			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
+			previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG);
             previewp->setThumbnailSubsampled(TRUE);     // We want the preview to reflect the *saved* image
             previewp->setAllowRenderUI(FALSE);          // We do not want the rendered UI in our snapshots
             previewp->setAllowFullScreenPreview(FALSE);  // No full screen preview in SL Share mode
-- 
cgit v1.2.3


From b0693c48ceb943dfae8d20183d101ec78a264da6 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Thu, 6 Feb 2014 00:37:26 +0000
Subject: Made Flickr tags persist between uploads for ACME-1303

---
 indra/newview/llfloaterflickr.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index ca1022d09d..2280d555e6 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -328,7 +328,6 @@ void LLFlickrPhotoPanel::clearAndClose()
 {
 	mTitleTextBox->setValue("");
 	mDescriptionTextBox->setValue("");
-	mTagsTextBox->setValue(DEFAULT_TAG_TEXT);
 
 	LLFloater* floater = getParentByType<LLFloater>();
 	if (floater)
-- 
cgit v1.2.3


From a6123336e20ad8e6b597437e808a22d9a9a46c6b Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Thu, 6 Feb 2014 00:42:11 +0000
Subject: Made Flickr rating default to Safe for ACME-1304

---
 indra/newview/llfloaterflickr.cpp                         | 2 +-
 indra/newview/skins/default/xui/en/panel_flickr_photo.xml | 7 +++----
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 2280d555e6..4ed32c3cf3 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -195,7 +195,7 @@ void LLFlickrPhotoPanel::draw()
     mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate()));
     
     // Enable Post if we have a preview to send and no on going connection being processed
-    mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()) && (mRatingComboBox && mRatingComboBox->getValue().isDefined()));
+    mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()));
     
     // Draw the rest of the panel on top of it
 	LLPanel::draw();
diff --git a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
index 01116c6c4c..4516c01670 100644
--- a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
@@ -183,21 +183,20 @@ Use "" for multi-word tags
              follows="left|top"
              top_pad="16"
              left="9"
-             label="Choose Flickr rating (required)..."
              name="rating_combobox"
              tool_tip="Flickr content rating"
              height="21"
              width="250">
               <combo_box.item
-               label="Safe content rating"
+               label="Safe Flickr rating"
                name="SafeRating"
                value="1" />
               <combo_box.item
-               label="Moderate content rating"
+               label="Moderate Flickr rating"
                name="ModerateRating"
                value="2" />
               <combo_box.item
-               label="Restricted content rating"
+               label="Restricted Flickr rating"
                name="RestrictedRating"
                value="3" />
             </combo_box>
-- 
cgit v1.2.3


From 225fb4e782108d83217b587188beb031afb04fef Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 5 Feb 2014 18:56:58 -0800
Subject: ACME-1300 : Rename blend mode dodge to add_back

---
 indra/llimage/llimagefilter.cpp | 8 ++++----
 indra/llimage/llimagefilter.h   | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index e0dae9fab2..7734b08c18 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -134,9 +134,9 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
             {
                 mode = STENCIL_BLEND_MODE_ADD;
             }
-            else if (filter_mode == "dodge")
+            else if (filter_mode == "add_back")
             {
-                mode = STENCIL_BLEND_MODE_DODGE;
+                mode = STENCIL_BLEND_MODE_ABACK;
             }
             else if (filter_mode == "fade")
             {
@@ -273,8 +273,8 @@ void LLImageFilter::blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue
             pixel[VGREEN] = llclampb(pixel[VGREEN] + alpha * green);
             pixel[VBLUE]  = llclampb(pixel[VBLUE]  + alpha * blue);
             break;
-        case STENCIL_BLEND_MODE_DODGE:
-            // Dodge/burn the incoming color onto the background image
+        case STENCIL_BLEND_MODE_ABACK:
+            // Add back background image to the incoming color
             pixel[VRED]   = llclampb(inv_alpha * pixel[VRED]   + red);
             pixel[VGREEN] = llclampb(inv_alpha * pixel[VGREEN] + green);
             pixel[VBLUE]  = llclampb(inv_alpha * pixel[VBLUE]  + blue);
diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h
index e392d3215e..d2650c2539 100755
--- a/indra/llimage/llimagefilter.h
+++ b/indra/llimage/llimagefilter.h
@@ -38,7 +38,7 @@ typedef enum e_stencil_blend_mode
 {
 	STENCIL_BLEND_MODE_BLEND = 0,
 	STENCIL_BLEND_MODE_ADD   = 1,
-	STENCIL_BLEND_MODE_DODGE = 2,
+	STENCIL_BLEND_MODE_ABACK = 2,
 	STENCIL_BLEND_MODE_FADE  = 3
 } EStencilBlendMode;
 
-- 
cgit v1.2.3


From 9112a47f9be023dd83bf4de72d490d21d85e6b5e Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Thu, 6 Feb 2014 10:26:25 -0800
Subject: ACME-1301 : Add convolve as a secondary filter command

---
 .../llimage_libtest/filters/convolve.xml              | 18 ++++++++++++++++++
 indra/llimage/llimagefilter.cpp                       | 19 +++++++++++++++----
 2 files changed, 33 insertions(+), 4 deletions(-)
 create mode 100644 indra/integration_tests/llimage_libtest/filters/convolve.xml

diff --git a/indra/integration_tests/llimage_libtest/filters/convolve.xml b/indra/integration_tests/llimage_libtest/filters/convolve.xml
new file mode 100644
index 0000000000..6e65b5f88a
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/convolve.xml
@@ -0,0 +1,18 @@
+<llsd>
+    <array>
+        <array>
+            <string>convolve</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>4.0</real>
+            <real>1.0</real>
+            <real>4.0</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>4.0</real>
+            <real>1.0</real>
+            <real>4.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index 7734b08c18..9093e4b59c 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -230,21 +230,32 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
         else if (filter_name == "sharpen")
         {
             LLMatrix3 kernel;
-            for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++)
+            for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++)
                 for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
-                    kernel.mMatrix[i][j] = -1.0;
+                    kernel.mMatrix[k][j] = -1.0;
             kernel.mMatrix[1][1] = 9.0;
             convolve(kernel,false,false);
         }
         else if (filter_name == "gradient")
         {
             LLMatrix3 kernel;
-            for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++)
+            for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++)
                 for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
-                    kernel.mMatrix[i][j] = -1.0;
+                    kernel.mMatrix[k][j] = -1.0;
             kernel.mMatrix[1][1] = 8.0;
             convolve(kernel,false,true);
         }
+        else if (filter_name == "convolve")
+        {
+            LLMatrix3 kernel;
+            S32 index = 1;
+            bool normalize = (mFilterData[i][index++].asReal() > 0.0);
+            bool abs_value = (mFilterData[i][index++].asReal() > 0.0);
+            for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++)
+                for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+                    kernel.mMatrix[k][j] = mFilterData[i][index++].asReal();
+            convolve(kernel,normalize,abs_value);
+        }
         else
         {
             llwarns << "Filter unknown, cannot execute filter command : " << filter_name << llendl;
-- 
cgit v1.2.3


From 2ba7552b9cd94b62c850365bcc537f0b3e344917 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Thu, 6 Feb 2014 11:57:01 -0800
Subject: ACME-1301 : Add colortransform as a secondary filter command

---
 .../llimage_libtest/filters/colortransform.xml           | 16 ++++++++++++++++
 indra/llimage/llimagefilter.cpp                          | 10 ++++++++++
 2 files changed, 26 insertions(+)
 create mode 100644 indra/integration_tests/llimage_libtest/filters/colortransform.xml

diff --git a/indra/integration_tests/llimage_libtest/filters/colortransform.xml b/indra/integration_tests/llimage_libtest/filters/colortransform.xml
new file mode 100644
index 0000000000..de4bebcce2
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/colortransform.xml
@@ -0,0 +1,16 @@
+<llsd>
+    <array>
+        <array>
+            <string>colortransform</string>
+            <real>0.2125</real>
+            <real>0.7154</real>
+            <real>0.0721</real>
+            <real>0.2125</real>
+            <real>0.7154</real>
+            <real>0.0721</real>
+            <real>0.2125</real>
+            <real>0.7154</real>
+            <real>0.0721</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index 9093e4b59c..8f7e340d16 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -256,6 +256,16 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
                     kernel.mMatrix[k][j] = mFilterData[i][index++].asReal();
             convolve(kernel,normalize,abs_value);
         }
+        else if (filter_name == "colortransform")
+        {
+            LLMatrix3 transform;
+            S32 index = 1;
+            for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++)
+                for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+                    transform.mMatrix[k][j] = mFilterData[i][index++].asReal();
+            transform.transpose();
+            colorTransform(transform);
+        }
         else
         {
             llwarns << "Filter unknown, cannot execute filter command : " << filter_name << llendl;
-- 
cgit v1.2.3


From 4e1c0f2c31475132f1d40cea96b243d7e99e00ff Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Thu, 6 Feb 2014 21:58:54 +0000
Subject: changed Facebook default image upload size to 1200x630 and Twitter to
 800x600

---
 indra/newview/llfloaterfacebook.cpp | 1 +
 indra/newview/llfloatertwitter.cpp  | 1 +
 2 files changed, 2 insertions(+)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 5e1e3ad40f..932d49811a 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -207,6 +207,7 @@ BOOL LLFacebookPhotoPanel::postBuild()
 	
 	mSnapshotPanel = getChild<LLUICtrl>("snapshot_panel");
 	mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
+	mResolutionComboBox->setValue("[i1200,i630]"); // hardcoded defaults ftw!
 	mResolutionComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE));
 	mFilterComboBox = getChild<LLUICtrl>("filters_combobox");
 	mFilterComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE));
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index 08b0cb6097..ab5a8e6859 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -91,6 +91,7 @@ BOOL LLTwitterPhotoPanel::postBuild()
 	
 	mSnapshotPanel = getChild<LLUICtrl>("snapshot_panel");
 	mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
+	mResolutionComboBox->setValue("[i800,i600]"); // hardcoded defaults ftw!
 	mResolutionComboBox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::updateResolution, this, TRUE));
 	mFilterComboBox = getChild<LLUICtrl>("filters_combobox");
 	mFilterComboBox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::updateResolution, this, TRUE));
-- 
cgit v1.2.3


From 968099312a70bf3c9a68254649a40eb4ec1ae928 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Thu, 6 Feb 2014 22:59:58 +0000
Subject: fixed SLShare connection state issues for ACME-1298

---
 indra/newview/llfacebookconnect.cpp | 5 +++--
 indra/newview/llflickrconnect.cpp   | 5 +++--
 indra/newview/lltwitterconnect.cpp  | 5 +++--
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index f9a3a21e94..e3ddb31935 100644
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -610,12 +610,13 @@ void LLFacebookConnect::setConnectionState(LLFacebookConnect::EConnectionState c
 
 	if (mConnectionState != connection_state)
 	{
+		// set the connection state before notifying watchers
+		mConnectionState = connection_state;
+
 		LLSD state_info;
 		state_info["enum"] = connection_state;
 		sStateWatcher->post(state_info);
 	}
-	
-	mConnectionState = connection_state;
 }
 
 void LLFacebookConnect::setConnected(bool connected)
diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp
index 8f9f55c1ea..c09e738a26 100644
--- a/indra/newview/llflickrconnect.cpp
+++ b/indra/newview/llflickrconnect.cpp
@@ -465,12 +465,13 @@ void LLFlickrConnect::setConnectionState(LLFlickrConnect::EConnectionState conne
 
 	if (mConnectionState != connection_state)
 	{
+		// set the connection state before notifying watchers
+		mConnectionState = connection_state;
+
 		LLSD state_info;
 		state_info["enum"] = connection_state;
 		sStateWatcher->post(state_info);
 	}
-	
-	mConnectionState = connection_state;
 }
 
 void LLFlickrConnect::setConnected(bool connected)
diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp
index 7942b21319..350da84f69 100644
--- a/indra/newview/lltwitterconnect.cpp
+++ b/indra/newview/lltwitterconnect.cpp
@@ -459,12 +459,13 @@ void LLTwitterConnect::setConnectionState(LLTwitterConnect::EConnectionState con
 
 	if (mConnectionState != connection_state)
 	{
+		// set the connection state before notifying watchers
+		mConnectionState = connection_state;
+
 		LLSD state_info;
 		state_info["enum"] = connection_state;
 		sStateWatcher->post(state_info);
 	}
-	
-	mConnectionState = connection_state;
 }
 
 void LLTwitterConnect::setConnected(bool connected)
-- 
cgit v1.2.3


From 8ad37cec70be671809f317bbc558eed1b59be595 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Thu, 6 Feb 2014 16:25:12 -0800
Subject: ACME-1278 : Allow angle to be used in 2D screen filter

---
 indra/llimage/llimagefilter.cpp | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index 8f7e340d16..8bd7416f6a 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -510,15 +510,18 @@ void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const
         {
             // Compute screen value
             F32 value = 0.0;
-            F32 d = 0.0;
+            F32 di = 0.0;
+            F32 dj = 0.0;
             switch (mode)
             {
                 case SCREEN_MODE_2DSINE:
-                    value = (sinf(2*F_PI*i/wave_length_pixels)*sinf(2*F_PI*j/wave_length_pixels)+1.0)*255.0/2.0;
+                    di =  cos*i + sin*j;
+                    dj = -sin*i + cos*j;
+                    value = (sinf(2*F_PI*di/wave_length_pixels)*sinf(2*F_PI*dj/wave_length_pixels)+1.0)*255.0/2.0;
                     break;
                 case SCREEN_MODE_LINE:
-                    d = sin*i - cos*j;
-                    value = (sinf(2*F_PI*d/wave_length_pixels)+1.0)*255.0/2.0;
+                    dj = sin*i - cos*j;
+                    value = (sinf(2*F_PI*dj/wave_length_pixels)+1.0)*255.0/2.0;
                     break;
             }
             U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0);
-- 
cgit v1.2.3


From 99427b29ceb8c6a22755075679ae008a37a947ae Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Thu, 6 Feb 2014 18:21:18 -0800
Subject: Clear up comments

---
 indra/llimage/llimagefilter.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index 8bd7416f6a..a5b5888bb2 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -76,9 +76,7 @@ LLImageFilter::~LLImageFilter()
 /*
  *TODO 
  * Rename stencil to mask
- * Test blend modes and name them correctly
  * Improve perf: use LUT for alpha blending in uniform case
- * Improve perf: make sure filter is not called more than necessary in viewer (seems to be called 3 times per change)
  * Add gradient coloring as a filter
  */
 
-- 
cgit v1.2.3


From 23727d02c8c941051a1aef8a51ecb493b65a2063 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Thu, 6 Feb 2014 18:23:54 -0800
Subject: ACME-1277 : Add a set of creative filters to the
 llimage_libtest/filters examples

---
 .../llimage_libtest/filters/badtrip.xml            |  36 ++++++
 .../llimage_libtest/filters/blowhighlights.xml     |  25 ++++
 .../llimage_libtest/filters/dodgeandburn.xml       |  47 +++++++
 .../llimage_libtest/filters/focus.xml              |  39 ++++++
 .../llimage_libtest/filters/lensflare.xml          | 138 +++++++++++++++++++++
 5 files changed, 285 insertions(+)
 create mode 100755 indra/integration_tests/llimage_libtest/filters/badtrip.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/blowhighlights.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/focus.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/lensflare.xml

diff --git a/indra/integration_tests/llimage_libtest/filters/badtrip.xml b/indra/integration_tests/llimage_libtest/filters/badtrip.xml
new file mode 100755
index 0000000000..14ee0baff3
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/badtrip.xml
@@ -0,0 +1,36 @@
+<llsd>
+    <array>
+        <array>
+            <string>grayscale</string>
+        </array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>posterize</string>
+            <real>10.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>gradient</string>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>0.15</real>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/blowhighlights.xml b/indra/integration_tests/llimage_libtest/filters/blowhighlights.xml
new file mode 100644
index 0000000000..2474a1b953
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/blowhighlights.xml
@@ -0,0 +1,25 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>uniform</string>
+            <string>add</string>
+            <real>0.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>gamma</string>
+            <real>0.25</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml b/indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml
new file mode 100644
index 0000000000..0e2e0ad68c
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml
@@ -0,0 +1,47 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>add</string>
+            <real>0.0</real>
+            <real>0.4</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>2.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>add</string>
+            <real>-0.8</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>2.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/focus.xml b/indra/integration_tests/llimage_libtest/filters/focus.xml
new file mode 100644
index 0000000000..d8525fea62
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/focus.xml
@@ -0,0 +1,39 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>blend</string>
+            <real>0.0</real>
+            <real>0.4</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>0.5</real>
+            <real>2.0</real>
+        </array>
+        <array>
+            <string>sharpen</string>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>blend</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>0.5</real>
+            <real>2.0</real>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/lensflare.xml b/indra/integration_tests/llimage_libtest/filters/lensflare.xml
new file mode 100644
index 0000000000..ec8afc8daa
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/lensflare.xml
@@ -0,0 +1,138 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.01</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>brighten</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>add</string>
+            <real>0.0</real>
+            <real>0.4</real>
+            <real>-0.5</real>
+            <real>0.5</real>
+            <real>0.15</real>
+            <real>20.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.15</real>
+            <real>0.15</real>
+            <real>0.15</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>add</string>
+            <real>0.0</real>
+            <real>0.4</real>
+            <real>-0.5</real>
+            <real>0.5</real>
+            <real>0.20</real>
+            <real>20.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.6</real>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>add</string>
+            <real>0.0</real>
+            <real>0.5</real>
+            <real>-0.7</real>
+            <real>0.7</real>
+            <real>0.10</real>
+            <real>20.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.6</real>
+            <real>0.6</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>add</string>
+            <real>0.0</real>
+            <real>0.5</real>
+            <real>0.5</real>
+            <real>-0.5</real>
+            <real>0.10</real>
+            <real>20.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.7</real>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>add</string>
+            <real>0.0</real>
+            <real>0.5</real>
+            <real>0.6</real>
+            <real>-0.6</real>
+            <real>0.05</real>
+            <real>20.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.7</real>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>add</string>
+            <real>0.0</real>
+            <real>0.5</real>
+            <real>0.4</real>
+            <real>-0.4</real>
+            <real>0.025</real>
+            <real>20.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.7</real>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
-- 
cgit v1.2.3


From d7f5afdc5dbbc5f2b9da031322d9e24669978c46 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Fri, 7 Feb 2014 11:31:04 -0800
Subject: ACME-1312 : Show the filter name without the Missing string prefix
 for filters that are not localized

---
 indra/newview/llimagefiltersmanager.cpp | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llimagefiltersmanager.cpp b/indra/newview/llimagefiltersmanager.cpp
index 0633dcaefc..ee6b39efac 100644
--- a/indra/newview/llimagefiltersmanager.cpp
+++ b/indra/newview/llimagefiltersmanager.cpp
@@ -74,10 +74,14 @@ void LLImageFiltersManager::loadFiltersFromDir(const std::string& dir)
 		}
 		
 		// Get the ".xml" out of the file name to get the filter name. That's the one known in strings.xml
-		std::string filter_name = file_name.substr(0,file_name.length()-4);
+		std::string filter_name_untranslated = file_name.substr(0,file_name.length()-4);
+        
         // Get the localized name for the filter
-		filter_name = LLTrans::getString(filter_name);
+        std::string	filter_name_translated;
+        bool translated = LLTrans::findString(filter_name_translated, filter_name_untranslated);
+        std::string	filter_name = (translated ? filter_name_translated: filter_name_untranslated);
         
+        // Store the filter in the list with its associated file name
         mFiltersList[filter_name] = file_name;
 	}
 }
-- 
cgit v1.2.3


From 73c9e42fafc0ad21af1ed38735c0ed9212640dd2 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Fri, 7 Feb 2014 16:27:42 -0800
Subject: ACME-1314 : Fix screen filter to make it less harsh on edges, modify
 Jules Verne and Newspaper filters as a result

---
 indra/llimage/llimagefilter.cpp                   | 10 +++++++++-
 indra/newview/app_settings/filters/JulesVerne.xml | 11 -----------
 indra/newview/app_settings/filters/Newspaper.xml  | 11 -----------
 3 files changed, 9 insertions(+), 23 deletions(-)

diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index a5b5888bb2..742b0ad802 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -500,6 +500,14 @@ void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const
     F32 wave_length_pixels = wave_length * (F32)(height) / 2.0;
     F32 sin = sinf(angle*DEG_TO_RAD);
     F32 cos = cosf(angle*DEG_TO_RAD);
+
+    // Precompute the gamma table : gives us the gray level to use when cutting outside the screen (prevents strong aliasing on the screen)
+    U8 gamma[256];
+    for (S32 i = 0; i < 256; i++)
+    {
+        F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,1.0/4.0)));
+        gamma[i] = (U8)(255.0 * gamma_i);
+    }
     
 	U8* dst_data = mImage->getData();
 	for (S32 j = 0; j < height; j++)
@@ -522,7 +530,7 @@ void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const
                     value = (sinf(2*F_PI*dj/wave_length_pixels)+1.0)*255.0/2.0;
                     break;
             }
-            U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0);
+            U8 dst_value = (dst_data[VRED] >= (U8)(value) ? gamma[dst_data[VRED] - (U8)(value)] : 0);
             
             // Blend result
             blendStencil(getStencilAlpha(i,j), dst_data, dst_value, dst_value, dst_value);
diff --git a/indra/newview/app_settings/filters/JulesVerne.xml b/indra/newview/app_settings/filters/JulesVerne.xml
index 35bc657c11..981e221da9 100644
--- a/indra/newview/app_settings/filters/JulesVerne.xml
+++ b/indra/newview/app_settings/filters/JulesVerne.xml
@@ -10,17 +10,6 @@
         <array>
             <string>grayscale</string>
         </array>
-        <array>
-            <string>stencil</string>
-            <string>vignette</string>
-            <string>blend</string>
-            <real>1.0</real>
-            <real>0.1</real>
-            <real>0.0</real>
-            <real>0.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
         <array>
             <string>screen</string>
             <string>line</string>
diff --git a/indra/newview/app_settings/filters/Newspaper.xml b/indra/newview/app_settings/filters/Newspaper.xml
index 8441decf3b..6cfe319281 100755
--- a/indra/newview/app_settings/filters/Newspaper.xml
+++ b/indra/newview/app_settings/filters/Newspaper.xml
@@ -10,17 +10,6 @@
         <array>
             <string>grayscale</string>
         </array>
-        <array>
-            <string>stencil</string>
-            <string>vignette</string>
-            <string>blend</string>
-            <real>1.0</real>
-            <real>0.1</real>
-            <real>0.0</real>
-            <real>0.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
         <array>
             <string>screen</string>
             <string>2Dsine</string>
-- 
cgit v1.2.3


From 51844473c00a7d620746c26af822aa7d41f53832 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Fri, 7 Feb 2014 18:35:46 -0800
Subject: ACME-1315 : Fix anisotropy in filters applied to thumbnail. Deleted
 some unused code

---
 indra/llimage/llimagefilter.cpp         | 25 -------------------------
 indra/llimage/llimagefilter.h           |  1 -
 indra/newview/llsnapshotlivepreview.cpp | 13 +++++--------
 3 files changed, 5 insertions(+), 34 deletions(-)

diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index 742b0ad802..3d0c488768 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -542,31 +542,6 @@ void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const
 //============================================================================
 // Procedural Stencils
 //============================================================================
-
-void LLImageFilter::setStencil(EStencilBlendMode mode, EStencilShape type, F32 gamma, F32 min, F32 max)
-{
-    mStencilBlendMode = mode;
-    mStencilShape = type;
-    mStencilGamma = gamma;
-    mStencilMin = llmin(llmax(min, -1.0f), 1.0f);
-    mStencilMax = llmin(llmax(max, -1.0f), 1.0f);
-
-    // We center the vignette on the image and fits it in the image smallest dimension
-    mStencilCenterX = mImage->getWidth()/2;
-    mStencilCenterY = mImage->getHeight()/2;
-    mStencilWidth = llmin(mImage->getWidth()/2,mImage->getHeight()/2);
-    
-    mStencilWavelength = gamma;
-    mStencilSine   = 0.0;
-    mStencilCosine = 1.0;
-    
-    mStencilStartX = 0.0;
-    mStencilStartY = 0.0;
-    mStencilGradX  = 0.0;
-    mStencilGradY  = (F32)(mImage->getHeight());
-    mStencilGradN  = (F32)(mImage->getHeight()*mImage->getHeight());
-}
-
 void LLImageFilter::setStencil(EStencilShape shape, EStencilBlendMode mode, F32 min, F32 max, F32* params)
 {
     mStencilShape = shape;
diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h
index d2650c2539..0f1cbc3fb8 100755
--- a/indra/llimage/llimagefilter.h
+++ b/indra/llimage/llimagefilter.h
@@ -94,7 +94,6 @@ private:
     void convolve(const LLMatrix3 &kernel, bool normalize, bool abs_value);
 
     // Procedural Stencils
-    void setStencil(EStencilBlendMode mode, EStencilShape type, F32 gamma, F32 min, F32 max);
     void setStencil(EStencilShape shape, EStencilBlendMode mode, F32 min, F32 max, F32* params);
     F32 getStencilAlpha(S32 i, S32 j);
 
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 2a5bd5d8bc..eef4ed78c8 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -556,10 +556,8 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
                      mPreviewImage->getHeight(),
                      mPreviewImage->getComponents());
         raw->copy(mPreviewImage);
-        // Scale to the thumbnal size modulo a power of 2
-        S32 width  = LLImageRaw::expandDimToPowerOfTwo(mThumbnailWidth,MAX_IMAGE_SIZE);
-        S32 height = LLImageRaw::expandDimToPowerOfTwo(mThumbnailHeight,MAX_IMAGE_SIZE);
-        if (!raw->scale(width, height))
+        // Scale to the thumbnail size
+        if (!raw->scale(mThumbnailWidth, mThumbnailHeight))
         {
             raw = NULL ;
         }
@@ -575,15 +573,12 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
         {
             raw = NULL ;
         }
-        else
-        {
-            raw->expandToPowerOfTwo();
-        }
     }
     
 	if (raw)
 	{
         // Filter the thumbnail
+        // Note: filtering needs to be done *before* the scaling to power of 2 or the effect is distorted
         if (getFilter() != "")
         {
             std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter());
@@ -597,6 +592,8 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
                 llwarns << "Couldn't find a path to the following filter : " << getFilter() << llendl;
             }
         }
+        // Scale to a power of 2 so it can be mapped to a texture
+        raw->expandToPowerOfTwo();
 		mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
 		mThumbnailUpToDate = TRUE ;
 	}
-- 
cgit v1.2.3


From 5f7e462d0f4cb3d9bdb84a51e8922b5e9130366c Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Mon, 10 Feb 2014 14:22:53 -0800
Subject: ACME-1318 : Handle No filter a bit more smartly so we don't fail on
 an unknown filter to do nothing...

---
 indra/newview/llfloaterfacebook.cpp | 3 ++-
 indra/newview/llfloaterflickr.cpp   | 3 ++-
 indra/newview/llfloatertwitter.cpp  | 3 ++-
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 932d49811a..3e58b40c75 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -463,7 +463,8 @@ void LLFacebookPhotoPanel::updateResolution(BOOL do_update)
 	S32 width = sdres[0];
 	S32 height = sdres[1];
 
-    const std::string& filter_name = filterbox->getSimple();
+    // Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale
+    std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : "");
 
 	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
 	if (previewp && combobox->getCurrentIndex() >= 0)
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 4ed32c3cf3..607b5b5df9 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -360,7 +360,8 @@ void LLFlickrPhotoPanel::updateResolution(BOOL do_update)
 	S32 width = sdres[0];
 	S32 height = sdres[1];
     
-    const std::string& filter_name = filterbox->getSimple();
+    // Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale 
+    std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : "");
 
 	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
 	if (previewp && combobox->getCurrentIndex() >= 0)
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index ab5a8e6859..c37e3ad396 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -422,7 +422,8 @@ void LLTwitterPhotoPanel::updateResolution(BOOL do_update)
 	S32 width = sdres[0];
 	S32 height = sdres[1];
 
-    const std::string& filter_name = filterbox->getSimple();
+    // Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale
+    std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : "");
 
 	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
 	if (previewp && combobox->getCurrentIndex() >= 0)
-- 
cgit v1.2.3


From de89552dc968f5b87c305fc661d15a50956a70d6 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Tue, 11 Feb 2014 00:37:46 +0000
Subject: Added #SecondLife to default Twitter status for ACME-1319

---
 indra/newview/llfloatertwitter.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index ab5a8e6859..d5039bd933 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -56,6 +56,7 @@ static LLRegisterPanelClassWrapper<LLTwitterAccountPanel> t_panel_account("lltwi
 const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
 const std::string DEFAULT_PHOTO_LOCATION_URL = "http://maps.secondlife.com/";
 const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=twitter&utm_medium=photo&utm_campaign=slshare";
+const std::string DEFAULT_STATUS_TEXT = " #SecondLife";
 
 ///////////////////////////
 //LLTwitterPhotoPanel///////
@@ -100,6 +101,7 @@ BOOL LLTwitterPhotoPanel::postBuild()
 	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
 	mStatusCounterLabel = getChild<LLUICtrl>("status_counter_label");
 	mStatusTextBox = getChild<LLUICtrl>("photo_status");
+	mStatusTextBox->setValue(DEFAULT_STATUS_TEXT);
 	mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
 	mLocationCheckbox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::onAddLocationToggled, this));
 	mPhotoCheckbox = getChild<LLUICtrl>("add_photo_cb");
@@ -351,7 +353,7 @@ void LLTwitterPhotoPanel::sendPhoto()
 
 void LLTwitterPhotoPanel::clearAndClose()
 {
-	mStatusTextBox->setValue("");
+	mStatusTextBox->setValue(DEFAULT_STATUS_TEXT);
 
 	LLFloater* floater = getParentByType<LLFloater>();
 	if (floater)
-- 
cgit v1.2.3


From bf0f20ef44de89c5852bfcfca29693b2c09f6a9c Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Wed, 12 Feb 2014 19:45:52 +0000
Subject: Changed Flickr link text for ACME-1320

---
 indra/newview/app_settings/filters/Video.xml | 22 ++++++++++++++++------
 indra/newview/llfloaterflickr.cpp            | 12 ++++++++++--
 2 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/indra/newview/app_settings/filters/Video.xml b/indra/newview/app_settings/filters/Video.xml
index aa65536235..fe17f3950a 100755
--- a/indra/newview/app_settings/filters/Video.xml
+++ b/indra/newview/app_settings/filters/Video.xml
@@ -9,26 +9,36 @@
         </array>
         <array>
             <string>darken</string>
-            <real>0.2</real>
+            <real>0.15</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
         </array>
         <array>
             <string>stencil</string>
-            <string>scanlines</string>
-            <string>blend</string>
+            <string>uniform</string>
+            <string>add</string>
             <real>0.0</real>
-            <real>1.0</real>
+            <real>0.5</real>
+        </array>
+        <array>
+            <string>screen</string>
+            <string>line</string>
             <real>0.02</real>
             <real>0.0</real>
         </array>
         <array>
-            <string>brighten</string>
-            <real>0.2</real>
+            <string>gamma</string>
+            <real>0.25</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
         </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
     </array>
 </llsd>
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 607b5b5df9..61f1487d4b 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -48,13 +48,13 @@
 #include "llviewercontrol.h"
 #include "llviewermedia.h"
 #include "lltabcontainer.h"
+#include "llviewerparcelmgr.h"
 
 static LLRegisterPanelClassWrapper<LLFlickrPhotoPanel> t_panel_photo("llflickrphotopanel");
 static LLRegisterPanelClassWrapper<LLFlickrAccountPanel> t_panel_account("llflickraccountpanel");
 
 const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
 const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=flickr&utm_medium=photo&utm_campaign=slshare";
-const std::string DEFAULT_PHOTO_LINK_TEXT = "Visit this location now";
 const std::string DEFAULT_TAG_TEXT = "secondlife ";
 
 ///////////////////////////
@@ -303,7 +303,15 @@ void LLFlickrPhotoPanel::sendPhoto()
 		// Add query parameters so Google Analytics can track incoming clicks!
 		slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS;
 
-		slurl_string = "<a href=\"" + slurl_string + "\">" + DEFAULT_PHOTO_LINK_TEXT + "</a>";
+		std::string photo_link_text = "Visit this location";// at [] in Second Life";
+		std::string parcel_name = LLViewerParcelMgr::getInstance()->getAgentParcelName();
+		if (!parcel_name.empty())
+		{
+			photo_link_text += " at " + parcel_name;
+		}
+		photo_link_text += " in Second Life";
+
+		slurl_string = "<a href=\"" + slurl_string + "\">" + photo_link_text + "</a>";
 
 		// Add it to the description (pretty crude, but we don't have a better option with photos)
 		if (description.empty())
-- 
cgit v1.2.3


From 2887d191ebd8bd9fff2a163e8b20acdeb4a82b5a Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 12 Feb 2014 17:05:03 -0800
Subject: ACME-1277 : Add new example filter scripts

---
 .../llimage_libtest/filters/autocontrast.xml       |  11 ++
 .../llimage_libtest/filters/lightleak.xml          |  78 ++++++++++++++
 .../llimage_libtest/filters/miniature.xml          | 118 +++++++++++++++++++++
 .../llimage_libtest/filters/pixelate.xml           |  18 ++++
 .../llimage_libtest/filters/thematrix.xml          |  42 ++++++++
 .../llimage_libtest/filters/toycamera.xml          |  46 ++++++++
 6 files changed, 313 insertions(+)
 create mode 100755 indra/integration_tests/llimage_libtest/filters/autocontrast.xml
 create mode 100755 indra/integration_tests/llimage_libtest/filters/lightleak.xml
 create mode 100755 indra/integration_tests/llimage_libtest/filters/miniature.xml
 create mode 100755 indra/integration_tests/llimage_libtest/filters/pixelate.xml
 create mode 100755 indra/integration_tests/llimage_libtest/filters/thematrix.xml
 create mode 100755 indra/integration_tests/llimage_libtest/filters/toycamera.xml

diff --git a/indra/integration_tests/llimage_libtest/filters/autocontrast.xml b/indra/integration_tests/llimage_libtest/filters/autocontrast.xml
new file mode 100755
index 0000000000..ec3d7561bd
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/autocontrast.xml
@@ -0,0 +1,11 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.01</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/lightleak.xml b/indra/integration_tests/llimage_libtest/filters/lightleak.xml
new file mode 100755
index 0000000000..6fe496506e
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/lightleak.xml
@@ -0,0 +1,78 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.01</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>brighten</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>gradient</string>
+            <string>add</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>-1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>-1.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.1</real>
+            <real>0.1</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>add</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>-1.0</real>
+            <real>1.0</real>
+            <real>1.5</real>
+            <real>5.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.8</real>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>add</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>-1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>5.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.8</real>
+            <real>0.8</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/miniature.xml b/indra/integration_tests/llimage_libtest/filters/miniature.xml
new file mode 100755
index 0000000000..9aa8a87c6f
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/miniature.xml
@@ -0,0 +1,118 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.02</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>1.02</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>saturate</string>
+            <real>1.2</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>blend</string>
+            <real>0.0</real>
+            <real>0.25</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>0.25</real>
+            <real>2.0</real>
+        </array>
+        <array>
+            <string>sharpen</string>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>gradient</string>
+            <string>blend</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>-1.0</real>
+            <real>0.0</real>
+            <real>-0.25</real>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>gradient</string>
+            <string>blend</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.25</real>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+    </array>
+</llsd>
\ No newline at end of file
diff --git a/indra/integration_tests/llimage_libtest/filters/pixelate.xml b/indra/integration_tests/llimage_libtest/filters/pixelate.xml
new file mode 100755
index 0000000000..4c9e8255fe
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/pixelate.xml
@@ -0,0 +1,18 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.01</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>posterize</string>
+            <real>5.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/thematrix.xml b/indra/integration_tests/llimage_libtest/filters/thematrix.xml
new file mode 100755
index 0000000000..af9a5eced8
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/thematrix.xml
@@ -0,0 +1,42 @@
+<llsd>
+    <array>
+        <array>
+            <string>grayscale</string>
+        </array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>posterize</string>
+            <real>50.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>gradient</string>
+        </array>
+        <array>
+            <string>screen</string>
+            <string>line</string>
+            <real>0.025</real>
+            <real>90.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.1</real>
+            <real>0.2</real>
+            <real>0.2</real>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+    </array>
+</llsd>
\ No newline at end of file
diff --git a/indra/integration_tests/llimage_libtest/filters/toycamera.xml b/indra/integration_tests/llimage_libtest/filters/toycamera.xml
new file mode 100755
index 0000000000..4e76f6b2fb
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/toycamera.xml
@@ -0,0 +1,46 @@
+<llsd>
+    <array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>fade</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.2</real>
+            <real>3.0</real>
+        </array>
+        <array>
+            <string>linearize</string>
+            <real>0.05</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>1.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>blend</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>0.5</real>
+            <real>2.0</real>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+    </array>
+</llsd>
\ No newline at end of file
-- 
cgit v1.2.3


From 170b5aed71446bf891ef4095812ccbfba7f4bab1 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Thu, 13 Feb 2014 19:54:58 +0000
Subject: Updated test filters

---
 .../llimage_libtest/filters/heatwave.xml           | 38 ++++++++++++++++++++++
 .../llimage_libtest/filters/overcast.xml           | 24 ++++++++++++++
 .../llimage_libtest/filters/pixelate.xml           | 21 ++++++++++--
 .../llimage_libtest/filters/video.xml              | 31 +++++++++++++++---
 4 files changed, 107 insertions(+), 7 deletions(-)
 create mode 100644 indra/integration_tests/llimage_libtest/filters/heatwave.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/overcast.xml

diff --git a/indra/integration_tests/llimage_libtest/filters/heatwave.xml b/indra/integration_tests/llimage_libtest/filters/heatwave.xml
new file mode 100644
index 0000000000..a99f41c833
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/heatwave.xml
@@ -0,0 +1,38 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>fade</string>
+            <real>0.5</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>4.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>0.4</real>
+            <real>0.0</real>
+            <real>0.2</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/overcast.xml b/indra/integration_tests/llimage_libtest/filters/overcast.xml
new file mode 100644
index 0000000000..dce5ab3e9e
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/overcast.xml
@@ -0,0 +1,24 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.3</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>saturate</string>
+            <real>0.35</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/pixelate.xml b/indra/integration_tests/llimage_libtest/filters/pixelate.xml
index 4c9e8255fe..f643419aa0 100755
--- a/indra/integration_tests/llimage_libtest/filters/pixelate.xml
+++ b/indra/integration_tests/llimage_libtest/filters/pixelate.xml
@@ -1,5 +1,22 @@
 <llsd>
     <array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>darken</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.9</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
         <array>
             <string>linearize</string>
             <real>0.01</real>
@@ -9,10 +26,10 @@
         </array>
         <array>
             <string>posterize</string>
-            <real>5.0</real>
+            <real>4.0</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
         </array>
     </array>
-</llsd>
+</llsd>
\ No newline at end of file
diff --git a/indra/integration_tests/llimage_libtest/filters/video.xml b/indra/integration_tests/llimage_libtest/filters/video.xml
index 8b10687ef5..fe17f3950a 100755
--- a/indra/integration_tests/llimage_libtest/filters/video.xml
+++ b/indra/integration_tests/llimage_libtest/filters/video.xml
@@ -2,22 +2,43 @@
     <array>
         <array>
             <string>linearize</string>
-            <real>0.01</real>
+            <real>0.0</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
         </array>
         <array>
-            <string>lines</string>
-            <real>10.0</real>
+            <string>darken</string>
+            <real>0.15</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>uniform</string>
+            <string>add</string>
             <real>0.0</real>
+            <real>0.5</real>
         </array>
         <array>
-            <string>brighten</string>
-            <real>100.0</real>
+            <string>screen</string>
+            <string>line</string>
+            <real>0.02</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>gamma</string>
+            <real>0.25</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
         </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
     </array>
 </llsd>
-- 
cgit v1.2.3


From a5366f06edf5aa1b75328e26011989eba7c601ca Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Thu, 13 Feb 2014 15:15:05 -0800
Subject: ACME-1277 : Final set of filters, added a SnapshotFiltersEnabled
 debug setting

---
 .../llimage_libtest/filters/heatwave.xml           |  38 ++++++
 .../llimage_libtest/filters/julesverne.xml         |  20 ++++
 .../llimage_libtest/filters/lensflare.xml          |  45 +++----
 .../llimage_libtest/filters/overcast.xml           |  24 ++++
 indra/llimage/llimagefilter.cpp                    |   2 +
 .../newview/app_settings/filters/Autocontrast.xml  |  11 ++
 indra/newview/app_settings/filters/Heatwave.xml    |  38 ------
 indra/newview/app_settings/filters/JulesVerne.xml  |  20 ----
 indra/newview/app_settings/filters/LensFlare.xml   | 131 +++++++++++++++++++++
 indra/newview/app_settings/filters/Miniature.xml   | 118 +++++++++++++++++++
 indra/newview/app_settings/filters/Overcast.xml    |  24 ----
 indra/newview/app_settings/filters/Spotlight.xml   |  38 +++---
 indra/newview/app_settings/filters/Toycamera.xml   |  46 ++++++++
 indra/newview/app_settings/settings.xml            |  11 ++
 indra/newview/llfloatersnapshot.cpp                |  41 +++++--
 .../skins/default/xui/en/floater_snapshot.xml      |   4 +-
 indra/newview/skins/default/xui/en/strings.xml     |  13 +-
 17 files changed, 473 insertions(+), 151 deletions(-)
 create mode 100644 indra/integration_tests/llimage_libtest/filters/heatwave.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/julesverne.xml
 create mode 100644 indra/integration_tests/llimage_libtest/filters/overcast.xml
 create mode 100755 indra/newview/app_settings/filters/Autocontrast.xml
 delete mode 100644 indra/newview/app_settings/filters/Heatwave.xml
 delete mode 100644 indra/newview/app_settings/filters/JulesVerne.xml
 create mode 100644 indra/newview/app_settings/filters/LensFlare.xml
 create mode 100755 indra/newview/app_settings/filters/Miniature.xml
 delete mode 100644 indra/newview/app_settings/filters/Overcast.xml
 create mode 100755 indra/newview/app_settings/filters/Toycamera.xml

diff --git a/indra/integration_tests/llimage_libtest/filters/heatwave.xml b/indra/integration_tests/llimage_libtest/filters/heatwave.xml
new file mode 100644
index 0000000000..a99f41c833
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/heatwave.xml
@@ -0,0 +1,38 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>0.8</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>fade</string>
+            <real>0.5</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>4.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>0.4</real>
+            <real>0.0</real>
+            <real>0.2</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/julesverne.xml b/indra/integration_tests/llimage_libtest/filters/julesverne.xml
new file mode 100644
index 0000000000..981e221da9
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/julesverne.xml
@@ -0,0 +1,20 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+        <array>
+            <string>screen</string>
+            <string>line</string>
+            <real>0.02</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/lensflare.xml b/indra/integration_tests/llimage_libtest/filters/lensflare.xml
index ec8afc8daa..0b5af9c82b 100644
--- a/indra/integration_tests/llimage_libtest/filters/lensflare.xml
+++ b/indra/integration_tests/llimage_libtest/filters/lensflare.xml
@@ -7,43 +7,36 @@
             <real>1.0</real>
             <real>1.0</real>
         </array>
-        <array>
-            <string>brighten</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
         <array>
             <string>stencil</string>
-            <string>vignette</string>
+            <string>gradient</string>
             <string>add</string>
+            <real>1.0</real>
             <real>0.0</real>
-            <real>0.4</real>
-            <real>-0.5</real>
-            <real>0.5</real>
-            <real>0.15</real>
-            <real>20.0</real>
+            <real>-1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>-1.0</real>
         </array>
         <array>
             <string>colorize</string>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
-            <real>0.15</real>
-            <real>0.15</real>
-            <real>0.15</real>
+            <real>0.1</real>
+            <real>0.1</real>
+            <real>0.0</real>
         </array>
         <array>
             <string>stencil</string>
             <string>vignette</string>
             <string>add</string>
             <real>0.0</real>
-            <real>0.4</real>
-            <real>-0.5</real>
-            <real>0.5</real>
-            <real>0.20</real>
-            <real>20.0</real>
+            <real>1.0</real>
+            <real>-1.0</real>
+            <real>1.0</real>
+            <real>1.5</real>
+            <real>5.0</real>
         </array>
         <array>
             <string>colorize</string>
@@ -59,11 +52,11 @@
             <string>vignette</string>
             <string>add</string>
             <real>0.0</real>
-            <real>0.5</real>
-            <real>-0.7</real>
-            <real>0.7</real>
-            <real>0.10</real>
-            <real>20.0</real>
+            <real>1.0</real>
+            <real>-1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>5.0</real>
         </array>
         <array>
             <string>colorize</string>
diff --git a/indra/integration_tests/llimage_libtest/filters/overcast.xml b/indra/integration_tests/llimage_libtest/filters/overcast.xml
new file mode 100644
index 0000000000..dce5ab3e9e
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/overcast.xml
@@ -0,0 +1,24 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.3</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>saturate</string>
+            <real>0.35</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index 3d0c488768..6e9ea2f948 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -55,6 +55,7 @@ LLImageFilter::LLImageFilter(const std::string& file_path) :
 {
     // Load filter description from file
 	llifstream filter_xml(file_path);
+    llinfos << "Merov : load filter : " << file_path << llendl;
 	if (filter_xml.is_open())
 	{
 		// Load and parse the file
@@ -88,6 +89,7 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
 {
     mImage = raw_image;
     
+    llinfos << "Merov : execute filter on image size " << mImage->getWidth() << "x" << mImage->getHeight() << llendl;
 	//std::cout << "Filter : size = " << mFilterData.size() << std::endl;
 	for (S32 i = 0; i < mFilterData.size(); ++i)
 	{
diff --git a/indra/newview/app_settings/filters/Autocontrast.xml b/indra/newview/app_settings/filters/Autocontrast.xml
new file mode 100755
index 0000000000..ec3d7561bd
--- /dev/null
+++ b/indra/newview/app_settings/filters/Autocontrast.xml
@@ -0,0 +1,11 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.01</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Heatwave.xml b/indra/newview/app_settings/filters/Heatwave.xml
deleted file mode 100644
index a99f41c833..0000000000
--- a/indra/newview/app_settings/filters/Heatwave.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>contrast</string>
-            <real>0.8</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>stencil</string>
-            <string>vignette</string>
-            <string>fade</string>
-            <real>0.5</real>
-            <real>1.0</real>
-            <real>0.0</real>
-            <real>0.0</real>
-            <real>1.0</real>
-            <real>4.0</real>
-        </array>
-        <array>
-            <string>colorize</string>
-            <real>1.0</real>
-            <real>0.0</real>
-            <real>1.0</real>
-            <real>0.4</real>
-            <real>0.0</real>
-            <real>0.2</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/JulesVerne.xml b/indra/newview/app_settings/filters/JulesVerne.xml
deleted file mode 100644
index 981e221da9..0000000000
--- a/indra/newview/app_settings/filters/JulesVerne.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>grayscale</string>
-        </array>
-        <array>
-            <string>screen</string>
-            <string>line</string>
-            <real>0.02</real>
-            <real>0.0</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/LensFlare.xml b/indra/newview/app_settings/filters/LensFlare.xml
new file mode 100644
index 0000000000..0b5af9c82b
--- /dev/null
+++ b/indra/newview/app_settings/filters/LensFlare.xml
@@ -0,0 +1,131 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.01</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>gradient</string>
+            <string>add</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>-1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>-1.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.1</real>
+            <real>0.1</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>add</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>-1.0</real>
+            <real>1.0</real>
+            <real>1.5</real>
+            <real>5.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.6</real>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>add</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>-1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>5.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.6</real>
+            <real>0.6</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>add</string>
+            <real>0.0</real>
+            <real>0.5</real>
+            <real>0.5</real>
+            <real>-0.5</real>
+            <real>0.10</real>
+            <real>20.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.7</real>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>add</string>
+            <real>0.0</real>
+            <real>0.5</real>
+            <real>0.6</real>
+            <real>-0.6</real>
+            <real>0.05</real>
+            <real>20.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.7</real>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>add</string>
+            <real>0.0</real>
+            <real>0.5</real>
+            <real>0.4</real>
+            <real>-0.4</real>
+            <real>0.025</real>
+            <real>20.0</real>
+        </array>
+        <array>
+            <string>colorize</string>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>0.7</real>
+            <real>0.0</real>
+            <real>0.0</real>
+        </array>
+    </array>
+</llsd>
diff --git a/indra/newview/app_settings/filters/Miniature.xml b/indra/newview/app_settings/filters/Miniature.xml
new file mode 100755
index 0000000000..9aa8a87c6f
--- /dev/null
+++ b/indra/newview/app_settings/filters/Miniature.xml
@@ -0,0 +1,118 @@
+<llsd>
+    <array>
+        <array>
+            <string>linearize</string>
+            <real>0.02</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>1.02</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>saturate</string>
+            <real>1.2</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>blend</string>
+            <real>0.0</real>
+            <real>0.25</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>0.25</real>
+            <real>2.0</real>
+        </array>
+        <array>
+            <string>sharpen</string>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>gradient</string>
+            <string>blend</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>-1.0</real>
+            <real>0.0</real>
+            <real>-0.25</real>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>gradient</string>
+            <string>blend</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.25</real>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+    </array>
+</llsd>
\ No newline at end of file
diff --git a/indra/newview/app_settings/filters/Overcast.xml b/indra/newview/app_settings/filters/Overcast.xml
deleted file mode 100644
index dce5ab3e9e..0000000000
--- a/indra/newview/app_settings/filters/Overcast.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<llsd>
-    <array>
-        <array>
-            <string>linearize</string>
-            <real>0.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-        </array>
-        <array>
-            <string>colorize</string>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>1.0</real>
-            <real>0.0</real>
-            <real>0.3</real>
-            <real>0.0</real>
-        </array>
-        <array>
-            <string>saturate</string>
-            <real>0.35</real>
-        </array>
-    </array>
-</llsd>
diff --git a/indra/newview/app_settings/filters/Spotlight.xml b/indra/newview/app_settings/filters/Spotlight.xml
index 044b2c0b3a..0e2e0ad68c 100644
--- a/indra/newview/app_settings/filters/Spotlight.xml
+++ b/indra/newview/app_settings/filters/Spotlight.xml
@@ -2,47 +2,43 @@
     <array>
         <array>
             <string>linearize</string>
-            <real>0.1</real>
+            <real>0.0</real>
+            <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>add</string>
+            <real>0.0</real>
+            <real>0.4</real>
+            <real>0.0</real>
+            <real>0.0</real>
             <real>1.0</real>
+            <real>2.0</real>
         </array>
         <array>
             <string>contrast</string>
-            <real>0.8</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
-        </array>
-        <array>
-            <string>saturate</string>
-            <real>1.5</real>
+            <real>1.0</real>
         </array>
         <array>
             <string>stencil</string>
             <string>vignette</string>
-            <string>fade</string>
-            <real>0.75</real>
-            <real>1.0</real>
+            <string>add</string>
+            <real>-0.8</real>
+            <real>0.0</real>
             <real>0.0</real>
             <real>0.0</real>
             <real>1.0</real>
-            <real>5.0</real>
-        </array>
-        <array>
-            <string>saturate</string>
-            <real>0.8</real>
+            <real>2.0</real>
         </array>
         <array>
             <string>contrast</string>
-            <real>1.1</real>
-            <real>1.0</real>
-            <real>1.0</real>
             <real>1.0</real>
-        </array>
-        <array>
-            <string>brighten</string>
-            <real>0.1</real>
             <real>1.0</real>
             <real>1.0</real>
             <real>1.0</real>
diff --git a/indra/newview/app_settings/filters/Toycamera.xml b/indra/newview/app_settings/filters/Toycamera.xml
new file mode 100755
index 0000000000..4e76f6b2fb
--- /dev/null
+++ b/indra/newview/app_settings/filters/Toycamera.xml
@@ -0,0 +1,46 @@
+<llsd>
+    <array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>fade</string>
+            <real>0.0</real>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>1.2</real>
+            <real>3.0</real>
+        </array>
+        <array>
+            <string>linearize</string>
+            <real>0.05</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>grayscale</string>
+        </array>
+        <array>
+            <string>contrast</string>
+            <real>1.1</real>
+            <real>1.0</real>
+            <real>1.0</real>
+            <real>1.0</real>
+        </array>
+        <array>
+            <string>stencil</string>
+            <string>vignette</string>
+            <string>blend</string>
+            <real>1.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>0.0</real>
+            <real>0.5</real>
+            <real>2.0</real>
+        </array>
+        <array>
+            <string>blur</string>
+        </array>
+    </array>
+</llsd>
\ No newline at end of file
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index afc4ac617c..43c82c3005 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -11268,6 +11268,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>SnapshotFiltersEnabled</key>
+    <map>
+        <key>Comment</key>
+        <string>Enable filters in the Snapshot Advanced panel (experimental).</string>
+        <key>Persist</key>
+        <integer>1</integer>
+        <key>Type</key>
+        <string>Boolean</string>
+        <key>Value</key>
+        <integer>0</integer>
+    </map>
     <key>SnapshotFormat</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 1d52ac5a69..8e48d35c1d 100755
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -478,9 +478,6 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
 		previewp->setSnapshotType(shot_type);
 		previewp->setSnapshotFormat(shot_format);
 		previewp->setSnapshotBufferType(layer_type);
-        // Filters
-        //const std::string& filter_name = floater->getChild<LLComboBox>("filters_combobox")->getSimple();
-        //previewp->setFilter(filter_name);
 	}
 
 	LLPanelSnapshot* current_panel = Impl::getActivePanel(floater);
@@ -575,8 +572,17 @@ void LLFloaterSnapshot::Impl::onClickFilter(LLUICtrl *ctrl, void* data)
 	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
 	if (view)
 	{
-		checkAutoSnapshot(getPreviewView(view));
 		updateControls(view);
+        LLSnapshotLivePreview* previewp = getPreviewView(view);
+        if (previewp)
+        {
+            checkAutoSnapshot(previewp);
+            // Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale
+            LLComboBox* filterbox = static_cast<LLComboBox *>(view->getChild<LLComboBox>("filters_combobox"));
+            std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : "");
+            previewp->setFilter(filter_name);
+            previewp->updateSnapshot(FALSE, TRUE);
+        }
 	}
 }
 
@@ -1078,16 +1084,25 @@ BOOL LLFloaterSnapshot::postBuild()
 	getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot"));
 	childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this);
     
-	// Update filter list
-    //std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
-	//LLComboBox* filterbox = getChild<LLComboBox>("filters_combobox");
-    //for (U32 i = 0; i < filter_list.size(); i++)
-	//{
-    //    filterbox->add(filter_list[i]);
-    //}
-	//childSetCommitCallback("filters_combobox", Impl::onClickFilter, this);
+	// Filters
+	LLComboBox* filterbox = getChild<LLComboBox>("filters_combobox");
+    if (gSavedSettings.getBOOL("SnapshotFiltersEnabled"))
+    {
+        // Update filter list if setting is on (experimental)
+        std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
+        for (U32 i = 0; i < filter_list.size(); i++)
+        {
+            filterbox->add(filter_list[i]);
+        }
+        childSetCommitCallback("filters_combobox", Impl::onClickFilter, this);
+    }
+    else
+    {
+        // Hide Filter UI if setting is off (default)
+        getChild<LLUICtrl>("filter_list_label")->setVisible(FALSE);
+        filterbox->setVisible(FALSE);
+    }
     
-	
 	LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUploadFinished, _1));
 	LLPostCard::setPostResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSendingPostcardFinished, _1));
 
diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml
index 5e3c7d4e3d..771035b40d 100755
--- a/indra/newview/skins/default/xui/en/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml
@@ -381,7 +381,6 @@
          top_pad="8"
          width="180"
          name="auto_snapshot_check" />
-        <!-- If we ever want to add filters to the snapshot panel...
         <text
          type="string"
          length="1"
@@ -389,7 +388,7 @@
          height="13"
          layout="topleft"
          left="10"
-         name="layer_type_label"
+         name="filter_list_label"
          top_pad="10"
          width="50">
             Filter:
@@ -408,6 +407,5 @@
             name="NoFilter"
             value="NoFilter" />
         </combo_box>
-         -->
     </panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 92913f678d..51576f71a8 100755
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -171,16 +171,17 @@ Please try logging in again in a minute.</string>
 	<!-- SLShare: User Friendly Filter Names Translation -->
     <string name="BlackAndWhite">Black &amp; White</string>
     <string name="Colors1970">1970&apos;s Colors</string>
-    <string name="Heatwave">Heat Wave</string>
     <string name="Intense">Intense</string>
-    <string name="JulesVerne">Jules Verne</string>
-    <string name="Newspaper">Newspaper</string>
-    <string name="Overcast">Overcast</string>
+    <string name="Newspaper">Newsprint</string>
     <string name="Sepia">Sepia</string>
     <string name="Spotlight">Spotlight</string>
     <string name="Video">Video</string>
-    
-	<!-- Tooltip -->
+    <string name="Autocontrast">Autocontrast</string>
+    <string name="LensFlare">Lens Flare</string>
+    <string name="Miniature">Miniature</string>
+    <string name="Toycamera">Toy Camera</string>
+	
+    <!-- Tooltip -->
 	<string name="TooltipPerson">Person</string><!-- Object under mouse pointer is an avatar -->
 	<string name="TooltipNoName">(no name)</string> <!-- No name on an object -->
 	<string name="TooltipOwner">Owner:</string> <!-- Owner name follows -->
-- 
cgit v1.2.3


From fc4efd18479f43766e7945d4ae8caf5e735f6563 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Fri, 14 Feb 2014 09:42:57 -0800
Subject: ACME-1277 : Delete debug printouts spamming the log

---
 indra/llimage/llimagefilter.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
index 6e9ea2f948..3d0c488768 100755
--- a/indra/llimage/llimagefilter.cpp
+++ b/indra/llimage/llimagefilter.cpp
@@ -55,7 +55,6 @@ LLImageFilter::LLImageFilter(const std::string& file_path) :
 {
     // Load filter description from file
 	llifstream filter_xml(file_path);
-    llinfos << "Merov : load filter : " << file_path << llendl;
 	if (filter_xml.is_open())
 	{
 		// Load and parse the file
@@ -89,7 +88,6 @@ void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
 {
     mImage = raw_image;
     
-    llinfos << "Merov : execute filter on image size " << mImage->getWidth() << "x" << mImage->getHeight() << llendl;
 	//std::cout << "Filter : size = " << mFilterData.size() << std::endl;
 	for (S32 i = 0; i < mFilterData.size(); ++i)
 	{
-- 
cgit v1.2.3


From 7bab501b816ec42ccada9b26e0cb112b74bd633c Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Fri, 14 Feb 2014 22:05:44 +0000
Subject: Reduced intensity of light leak on Lens Flare filter for ACME-1277

---
 indra/newview/app_settings/filters/LensFlare.xml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/indra/newview/app_settings/filters/LensFlare.xml b/indra/newview/app_settings/filters/LensFlare.xml
index 0b5af9c82b..e9aef6eea4 100644
--- a/indra/newview/app_settings/filters/LensFlare.xml
+++ b/indra/newview/app_settings/filters/LensFlare.xml
@@ -11,7 +11,7 @@
             <string>stencil</string>
             <string>gradient</string>
             <string>add</string>
-            <real>1.0</real>
+            <real>0.5</real>
             <real>0.0</real>
             <real>-1.0</real>
             <real>1.0</real>
@@ -32,7 +32,7 @@
             <string>vignette</string>
             <string>add</string>
             <real>0.0</real>
-            <real>1.0</real>
+            <real>0.5</real>
             <real>-1.0</real>
             <real>1.0</real>
             <real>1.5</real>
@@ -52,7 +52,7 @@
             <string>vignette</string>
             <string>add</string>
             <real>0.0</real>
-            <real>1.0</real>
+            <real>0.5</real>
             <real>-1.0</real>
             <real>1.0</real>
             <real>1.0</real>
-- 
cgit v1.2.3


From ac9cf045ecc14f8c650773f3fff7bc338fa468d0 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Fri, 21 Feb 2014 02:06:03 +0000
Subject: Added Friends tab to Facebook floater for ACME-1325

---
 indra/newview/llfloaterfacebook.cpp                | 99 ++++++++++++++++++++++
 indra/newview/llfloaterfacebook.h                  | 16 +++-
 indra/newview/llpanelpeople.cpp                    |  6 +-
 indra/newview/llpanelpeople.h                      |  2 +-
 .../skins/default/xui/en/floater_facebook.xml      | 10 ++-
 .../default/xui/en/panel_facebook_friends.xml      | 35 ++++++++
 6 files changed, 161 insertions(+), 7 deletions(-)
 create mode 100644 indra/newview/skins/default/xui/en/panel_facebook_friends.xml

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 3e58b40c75..de849b6b3f 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -48,10 +48,13 @@
 #include "llviewercontrol.h"
 #include "llviewermedia.h"
 #include "lltabcontainer.h"
+#include "llavatarlist.h"
+#include "llpanelpeoplemenus.h"
 
 static LLRegisterPanelClassWrapper<LLFacebookStatusPanel> t_panel_status("llfacebookstatuspanel");
 static LLRegisterPanelClassWrapper<LLFacebookPhotoPanel> t_panel_photo("llfacebookphotopanel");
 static LLRegisterPanelClassWrapper<LLFacebookCheckinPanel> t_panel_checkin("llfacebookcheckinpanel");
+static LLRegisterPanelClassWrapper<LLFacebookFriendsPanel> t_panel_friends("llfacebookfriendspanel");
 static LLRegisterPanelClassWrapper<LLFacebookAccountPanel> t_panel_account("llfacebookaccountpanel");
 
 const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
@@ -692,6 +695,102 @@ void LLFacebookCheckinPanel::clearAndClose()
 	}
 }
 
+///////////////////////////
+//LLFacebookFriendsPanel//////
+///////////////////////////
+
+LLFacebookFriendsPanel::LLFacebookFriendsPanel() : 
+mSuggestedFriends(NULL)
+{
+}
+
+BOOL LLFacebookFriendsPanel::postBuild()
+{
+	mSuggestedFriends = getChild<LLAvatarList>("suggested_friends");
+	mSuggestedFriends->setContextMenu(&LLPanelPeopleMenus::gSuggestedFriendsContextMenu);
+	
+	setVisibleCallback(boost::bind(&LLFacebookFriendsPanel::updateFacebookList, this, _2));
+
+	return LLPanel::postBuild();
+}
+
+bool LLFacebookFriendsPanel::updateSuggestedFriendList()
+{
+	const LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
+	uuid_vec_t& suggested_friends = mSuggestedFriends->getIDs();
+	suggested_friends.clear();
+
+	//Add suggested friends
+	LLSD friends = LLFacebookConnect::instance().getContent();
+	for (LLSD::array_const_iterator i = friends.beginArray(); i != friends.endArray(); ++i)
+	{
+		LLUUID agent_id = (*i).asUUID();
+		bool second_life_buddy = agent_id.notNull() ? av_tracker.isBuddy(agent_id) : false;
+
+		if(!second_life_buddy)
+		{
+			//FB+SL but not SL friend
+			if (agent_id.notNull())
+			{
+				suggested_friends.push_back(agent_id);
+			}
+		}
+	}
+
+	//Force a refresh when there aren't any filter matches (prevent displaying content that shouldn't display)
+	mSuggestedFriends->setDirty(true, !mSuggestedFriends->filterHasMatches());
+	//showFriendsAccordionsIfNeeded();
+
+	return false;
+}
+
+void LLFacebookFriendsPanel::updateFacebookList(bool visible)
+{
+	if (visible)
+	{
+		LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLPanelPeople"); // just in case it is already listening
+		LLEventPumps::instance().obtain("FacebookConnectContent").listen("LLPanelPeople", boost::bind(&LLFacebookFriendsPanel::updateSuggestedFriendList, this));
+
+		LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLPanelPeople"); // just in case it is already listening
+		LLEventPumps::instance().obtain("FacebookConnectState").listen("LLPanelPeople", boost::bind(&LLFacebookFriendsPanel::onConnectedToFacebook, this, _1));
+
+		//Connected
+		if (LLFacebookConnect::instance().isConnected())
+		{
+			LLFacebookConnect::instance().loadFacebookFriends();
+		}
+		//Check if connected
+        if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) ||
+            (LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED))
+        {
+            LLFacebookConnect::instance().checkConnectionToFacebook();
+        }
+
+		updateSuggestedFriendList();
+	}
+	else
+	{
+		LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLPanelPeople");
+		LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLPanelPeople");
+	}
+}
+
+bool LLFacebookFriendsPanel::onConnectedToFacebook(const LLSD& data)
+{
+	LLSD::Integer connection_state = data.get("enum").asInteger();
+
+	if (connection_state == LLFacebookConnect::FB_CONNECTED)
+	{
+		LLFacebookConnect::instance().loadFacebookFriends();
+	}
+	else if(connection_state == LLFacebookConnect::FB_NOT_CONNECTED)
+	{
+		updateSuggestedFriendList();
+	};
+
+	return false;
+}
+
 ///////////////////////////
 //LLFacebookAccountPanel//////
 ///////////////////////////
diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h
index 4361dfa628..20c401d0c1 100644
--- a/indra/newview/llfloaterfacebook.h
+++ b/indra/newview/llfloaterfacebook.h
@@ -34,6 +34,7 @@
 class LLIconCtrl;
 class LLCheckBoxCtrl;
 class LLSnapshotLivePreview;
+class LLAvatarList;
 
 class LLFacebookStatusPanel : public LLPanel
 {
@@ -119,6 +120,20 @@ private:
     bool mReloadingMapTexture;
 };
 
+class LLFacebookFriendsPanel : public LLPanel
+{
+public:
+	LLFacebookFriendsPanel();
+	BOOL postBuild();
+
+private:
+	bool updateSuggestedFriendList();
+	void updateFacebookList(bool visible);
+	bool onConnectedToFacebook(const LLSD& data);
+	
+	LLAvatarList* mSuggestedFriends;
+};
+
 class LLFacebookAccountPanel : public LLPanel
 {
 public:
@@ -146,7 +161,6 @@ private:
 	LLUICtrl * mDisconnectButton;
 };
 
-
 class LLFloaterFacebook : public LLFloater
 {
 public:
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index f551fc96ee..b2e733e1ae 100755
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -505,7 +505,7 @@ public:
 
 LLPanelPeople::LLPanelPeople()
 	:	LLPanel(),
-		mTryToConnectToFbc(true),
+		mTryToConnectToFacebook(true),
 		mTabContainer(NULL),
 		mOnlineFriendList(NULL),
 		mAllFriendList(NULL),
@@ -865,10 +865,10 @@ void LLPanelPeople::updateFacebookList(bool visible)
 		{
 			LLFacebookConnect::instance().loadFacebookFriends();
 		}
-		else if(mTryToConnectToFbc)
+		else if(mTryToConnectToFacebook)
 		{
 			LLFacebookConnect::instance().checkConnectionToFacebook();
-			mTryToConnectToFbc = false;
+			mTryToConnectToFacebook = false;
 		}
     
 		updateSuggestedFriendList();
diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h
index c7141f36ee..67e190dafd 100755
--- a/indra/newview/llpanelpeople.h
+++ b/indra/newview/llpanelpeople.h
@@ -56,7 +56,7 @@ public:
 	// when voice is available
 	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
 
-    bool mTryToConnectToFbc;
+    bool mTryToConnectToFacebook;
 
 	// internals
 	class Updater;
diff --git a/indra/newview/skins/default/xui/en/floater_facebook.xml b/indra/newview/skins/default/xui/en/floater_facebook.xml
index c1ff8571e9..544c443c76 100644
--- a/indra/newview/skins/default/xui/en/floater_facebook.xml
+++ b/indra/newview/skins/default/xui/en/floater_facebook.xml
@@ -48,13 +48,19 @@
        follows="all"
        label="CHECK IN"
        name="panel_facebook_place"/>
+     <panel
+       filename="panel_facebook_friends.xml"
+       class="llfacebookfriendspanel"
+       follows="all"
+       label="FRIENDS"
+       name="panel_facebook_friends"/>
      <panel
        filename="panel_facebook_account.xml"
        class="llfacebookaccountpanel"
        follows="all"
        label="ACCOUNT"
-       name="panel_facebook_account"/>     
-    </tab_container>
+       name="panel_facebook_account"/>
+   </tab_container>
     <panel
      name="connection_status_panel"
      follows="left|bottom|right"
diff --git a/indra/newview/skins/default/xui/en/panel_facebook_friends.xml b/indra/newview/skins/default/xui/en/panel_facebook_friends.xml
new file mode 100644
index 0000000000..d772dde0c5
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_facebook_friends.xml
@@ -0,0 +1,35 @@
+<panel
+	 height="400"
+	 width="304"
+	 layout="topleft"
+   name="panel_facebook_friends">
+  <accordion
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ bg_opaque_color="DkGray2"
+   follows="all"
+   height="408"
+   layout="topleft"
+   left="3"
+   name="friends_accordion"
+   right="-2"
+   top_pad="2">
+    <accordion_tab
+     layout="topleft"
+     height="173"
+     name="tab_suggested_friends"
+     title="People you may want to friend">
+      <avatar_list
+       ignore_online_status="true"
+       allow_select="true"
+       follows="all"
+       height="173"
+       layout="topleft"
+       left="0"
+       name="suggested_friends"
+       show_permissions_granted="true"
+       top="0"
+       width="307" />
+    </accordion_tab>
+  </accordion>
+</panel>
-- 
cgit v1.2.3


From 64c239fbf7f1fb668d94b9c26f413858058b8270 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Wed, 26 Feb 2014 00:32:49 +0000
Subject: Added machine tags to Flickr uploads for ACME-1323

---
 indra/newview/llfloaterflickr.cpp | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 61f1487d4b..8c3db46d76 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -49,6 +49,7 @@
 #include "llviewermedia.h"
 #include "lltabcontainer.h"
 #include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
 
 static LLRegisterPanelClassWrapper<LLFlickrPhotoPanel> t_panel_photo("llflickrphotopanel");
 static LLRegisterPanelClassWrapper<LLFlickrAccountPanel> t_panel_account("llflickraccountpanel");
@@ -56,6 +57,7 @@ static LLRegisterPanelClassWrapper<LLFlickrAccountPanel> t_panel_account("llflic
 const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
 const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=flickr&utm_medium=photo&utm_campaign=slshare";
 const std::string DEFAULT_TAG_TEXT = "secondlife ";
+const std::string FLICKR_MACHINE_TAGS_NAMESPACE = "secondlife";
 
 ///////////////////////////
 //LLFlickrPhotoPanel///////
@@ -318,6 +320,26 @@ void LLFlickrPhotoPanel::sendPhoto()
 			description = slurl_string;
 		else
 			description = description + "\n\n" + slurl_string;
+
+		// Also add special "machine tags" with location metadata
+		const LLVector3& agent_pos_region = gAgent.getPositionAgent();
+		LLViewerRegion* region = gAgent.getRegion();
+		LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+		if (region && parcel)
+		{
+			S32 pos_x = S32(agent_pos_region.mV[VX]);
+			S32 pos_y = S32(agent_pos_region.mV[VY]);
+			S32 pos_z = S32(agent_pos_region.mV[VZ]);
+			
+			std::string parcel_name = LLViewerParcelMgr::getInstance()->getAgentParcelName();
+			std::string region_name = region->getName();
+			
+			tags += llformat(" \"%s:region=%s\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), region_name.c_str());
+			tags += llformat(" \"%s:parcel=%s\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), parcel_name.c_str());
+			tags += llformat(" \"%s:x=%d\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), pos_x);
+			tags += llformat(" \"%s:y=%d\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), pos_y);
+			tags += llformat(" \"%s:z=%d\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), pos_z);
+		}
 	}
 
 	// Get the content rating
-- 
cgit v1.2.3


From d220657d8525ccfa246e0f49904e18cc36458b28 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 25 Feb 2014 21:54:09 -0800
Subject: ACME-1327 : WIP : Added big preview to the Flickr photo panel, uses
 the thumbnail for the moment

---
 indra/newview/CMakeLists.txt                       |   2 +
 indra/newview/llfloaterbigpreview.cpp              | 109 +++++++++++++++++++++
 indra/newview/llfloaterbigpreview.h                |  56 +++++++++++
 indra/newview/llfloaterflickr.cpp                  |  36 ++++++-
 indra/newview/llfloaterflickr.h                    |   2 +
 indra/newview/llsnapshotlivepreview.h              |   2 +-
 indra/newview/llviewerfloaterreg.cpp               |   2 +
 .../skins/default/xui/en/floater_big_preview.xml   |  25 +++++
 .../skins/default/xui/en/panel_flickr_photo.xml    |  17 +++-
 9 files changed, 247 insertions(+), 4 deletions(-)
 create mode 100644 indra/newview/llfloaterbigpreview.cpp
 create mode 100644 indra/newview/llfloaterbigpreview.h
 create mode 100644 indra/newview/skins/default/xui/en/floater_big_preview.xml

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 793d972e1c..6d8d6b75a2 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -208,6 +208,7 @@ set(viewer_SOURCE_FILES
     llfloateravatarpicker.cpp
     llfloateravatartextures.cpp
     llfloaterbeacons.cpp
+    llfloaterbigpreview.cpp
     llfloaterbuildoptions.cpp
     llfloaterbulkpermission.cpp
     llfloaterbump.cpp
@@ -802,6 +803,7 @@ set(viewer_HEADER_FILES
     llfloateravatarpicker.h
     llfloateravatartextures.h
     llfloaterbeacons.h
+    llfloaterbigpreview.h
     llfloaterbuildoptions.h
     llfloaterbulkpermission.h
     llfloaterbump.h
diff --git a/indra/newview/llfloaterbigpreview.cpp b/indra/newview/llfloaterbigpreview.cpp
new file mode 100644
index 0000000000..84a1523e7c
--- /dev/null
+++ b/indra/newview/llfloaterbigpreview.cpp
@@ -0,0 +1,109 @@
+/** 
+* @file llfloaterbigpreview.cpp
+* @brief Display of extended (big) preview for snapshots and SL Share
+* @author merov@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterbigpreview.h"
+
+#include "llfloaterreg.h"
+#include "llsnapshotlivepreview.h"
+
+///////////////////////
+//LLFloaterBigPreview//
+///////////////////////
+
+LLFloaterBigPreview::LLFloaterBigPreview(const LLSD& key) : LLFloater(key),
+    mPreviewPlaceholder(NULL),
+    mFloaterOwner(NULL)
+{
+}
+
+LLFloaterBigPreview::~LLFloaterBigPreview()
+{
+	if (mPreviewHandle.get())
+	{
+		mPreviewHandle.get()->die();
+	}
+}
+
+void LLFloaterBigPreview::onCancel()
+{
+    closeFloater();
+}
+
+void LLFloaterBigPreview::closeOnFloaterOwnerClosing(LLFloater* floaterp)
+{
+    if (floaterp == mFloaterOwner)
+    {
+        closeFloater();
+    }
+}
+
+BOOL LLFloaterBigPreview::postBuild()
+{
+	mPreviewPlaceholder = getChild<LLUICtrl>("big_preview_placeholder");
+	return LLFloater::postBuild();
+}
+
+void LLFloaterBigPreview::draw()
+{
+	LLFloater::draw();
+
+	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
+    
+    // Display the preview if one is available
+    // HACK!!! We use the puny thumbnail image for the moment
+    // *TODO : Use the real large preview
+	if (previewp && previewp->getThumbnailImage())
+	{
+		const LLRect& preview_rect = mPreviewPlaceholder->getRect();
+//		const S32 thumbnail_w = previewp->getThumbnailWidth();
+//		const S32 thumbnail_h = previewp->getThumbnailHeight();
+        
+		// calc preview offset within the preview rect
+//		const S32 local_offset_x = (preview_rect.getWidth()  - thumbnail_w) / 2 ;
+//		const S32 local_offset_y = (preview_rect.getHeight() - thumbnail_h) / 2 ;
+		const S32 local_offset_x = 0 ;
+		const S32 local_offset_y = 0 ;
+        
+		// calc preview offset within the floater rect
+		S32 offset_x = preview_rect.mLeft   + local_offset_x;
+		S32 offset_y = preview_rect.mBottom + local_offset_y;
+        
+        //llinfos << "Merov : draw, offset x = " << offset_x  << ", y = " <<  offset_y << ", thumbnail w = " <<  thumbnail_w << ", h = " <<  thumbnail_h << ", rect w = " << preview_rect.getWidth() << ", h = " << preview_rect.getHeight() << llendl;
+        
+		gGL.matrixMode(LLRender::MM_MODELVIEW);
+		// Apply floater transparency to the texture unless the floater is focused.
+		F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
+		LLColor4 color = LLColor4::white;
+		gl_draw_scaled_image(offset_x, offset_y,
+                             //thumbnail_w, thumbnail_h,
+                             preview_rect.getWidth(), preview_rect.getHeight(),
+                             previewp->getThumbnailImage(), color % alpha);
+	}
+}
+
diff --git a/indra/newview/llfloaterbigpreview.h b/indra/newview/llfloaterbigpreview.h
new file mode 100644
index 0000000000..91b0968e88
--- /dev/null
+++ b/indra/newview/llfloaterbigpreview.h
@@ -0,0 +1,56 @@
+/** 
+* @file   llfloaterbigpreview.h
+* @brief  Display of extended (big) preview for snapshots and SL Share
+* @author merov@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+#ifndef LL_LLFLOATERBIGPREVIEW_H
+#define LL_LLFLOATERBIGPREVIEW_H
+
+#include "llfloater.h"
+#include "llviewertexture.h"
+
+//class LLSnapshotLivePreview;
+
+class LLFloaterBigPreview : public LLFloater
+{
+public:
+	LLFloaterBigPreview(const LLSD& key);
+    ~LLFloaterBigPreview();
+    
+	BOOL postBuild();
+	void draw();
+	void onCancel();
+
+    void setPreview(LLView* previewp) { mPreviewHandle = previewp->getHandle(); }
+    void setFloaterOwner(LLFloater* floaterp) { mFloaterOwner = floaterp; }
+    void closeOnFloaterOwnerClosing(LLFloater* floaterp);
+	
+private:
+	LLHandle<LLView> mPreviewHandle;
+	LLUICtrl*  mPreviewPlaceholder;
+    LLFloater* mFloaterOwner;
+};
+
+#endif // LL_LLFLOATERBIGPREVIEW_H
+
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 61f1487d4b..21c619730c 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -44,6 +44,7 @@
 #include "llslurl.h"
 #include "lltrans.h"
 #include "llsnapshotlivepreview.h"
+#include "llfloaterbigpreview.h"
 #include "llviewerregion.h"
 #include "llviewercontrol.h"
 #include "llviewermedia.h"
@@ -76,6 +77,7 @@ mPostButton(NULL)
 {
 	mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFlickrPhotoPanel::onSend, this));
 	mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFlickrPhotoPanel::onClickNewSnapshot, this));
+	mCommitCallbackRegistrar.add("SocialSharing.BigPreview", boost::bind(&LLFlickrPhotoPanel::onClickBigPreview, this));
 }
 
 LLFlickrPhotoPanel::~LLFlickrPhotoPanel()
@@ -227,7 +229,7 @@ void LLFlickrPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
 			LLSnapshotLivePreview::Params p;
 			p.rect(full_screen_rect);
 			LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
-			mPreviewHandle = previewp->getHandle();	
+			mPreviewHandle = previewp->getHandle();
 
             previewp->setContainer(this);
 			previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
@@ -251,6 +253,18 @@ void LLFlickrPhotoPanel::onClickNewSnapshot()
 	}
 }
 
+void LLFlickrPhotoPanel::onClickBigPreview()
+{
+	LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
+	if (big_preview_floater)
+	{
+        LLSnapshotLivePreview* previewp = getPreviewView();
+		big_preview_floater->setPreview(previewp);
+        big_preview_floater->setFloaterOwner(getParentByType<LLFloater>());
+	}
+	LLFloaterReg::showInstance("big_preview");
+}
+
 void LLFlickrPhotoPanel::onSend()
 {
 	LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrPhotoPanel"); // just in case it is already listening
@@ -340,6 +354,11 @@ void LLFlickrPhotoPanel::clearAndClose()
 	LLFloater* floater = getParentByType<LLFloater>();
 	if (floater)
 	{
+        LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
+        if (big_preview_floater)
+        {
+            big_preview_floater->closeOnFloaterOwnerClosing(floater);
+        }
 		floater->closeFloater();
 	}
 }
@@ -615,8 +634,23 @@ LLFloaterFlickr::LLFloaterFlickr(const LLSD& key) : LLFloater(key),
 	mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterFlickr::onCancel, this));
 }
 
+void LLFloaterFlickr::onClose(bool app_quitting)
+{
+    LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
+    if (big_preview_floater)
+    {
+        big_preview_floater->closeOnFloaterOwnerClosing(this);
+    }
+	LLFloater::onClose(app_quitting);
+}
+
 void LLFloaterFlickr::onCancel()
 {
+    LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
+    if (big_preview_floater)
+    {
+        big_preview_floater->closeOnFloaterOwnerClosing(this);
+    }
     closeFloater();
 }
 
diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h
index 319ab1278f..9fa4a258e2 100644
--- a/indra/newview/llfloaterflickr.h
+++ b/indra/newview/llfloaterflickr.h
@@ -48,6 +48,7 @@ public:
 	LLSnapshotLivePreview* getPreviewView();
 	void onVisibilityChange(const LLSD& new_visibility);
 	void onClickNewSnapshot();
+    void onClickBigPreview();
 	void onSend();
 	bool onFlickrConnectStateChange(const LLSD& data);
 
@@ -111,6 +112,7 @@ public:
 	LLFloaterFlickr(const LLSD& key);
 	BOOL postBuild();
 	void draw();
+	void onClose(bool app_quitting);
 	void onCancel();
 	
 	void showPhotoPanel();
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index 7f3e7a080b..1b7b5290f8 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -113,7 +113,7 @@ public:
 	LLPointer<LLImageFormatted>	getFormattedImage();
 	LLPointer<LLImageRaw>		getEncodedImage();
 
-	/// Sets size of preview thumbnail image and thhe surrounding rect.
+	/// Sets size of preview thumbnail image and the surrounding rect.
 	void setThumbnailPlaceholderRect(const LLRect& rect) {mThumbnailPlaceholderRect = rect; }
 	BOOL setThumbnailImageSize() ;
 	void generateThumbnailImage(BOOL force_update = FALSE) ;
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 1f25110aa3..982522955c 100755
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -38,6 +38,7 @@
 #include "llfloateravatar.h"
 #include "llfloateravatarpicker.h"
 #include "llfloateravatartextures.h"
+#include "llfloaterbigpreview.h"
 #include "llfloaterbeacons.h"
 #include "llfloaterbuildoptions.h"
 #include "llfloaterbuy.h"
@@ -324,6 +325,7 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterReg::add("facebook", "floater_facebook.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFacebook>);
 	LLFloaterReg::add("flickr", "floater_flickr.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFlickr>);
 	LLFloaterReg::add("twitter", "floater_twitter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTwitter>);
+	LLFloaterReg::add("big_preview", "floater_big_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBigPreview>);
 	
 	LLFloaterUIPreviewUtil::registerFloater();
 	LLFloaterReg::add("upload_anim_bvh", "floater_animation_bvh_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBvhPreview>, "upload");
diff --git a/indra/newview/skins/default/xui/en/floater_big_preview.xml b/indra/newview/skins/default/xui/en/floater_big_preview.xml
new file mode 100644
index 0000000000..23698ccc40
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_big_preview.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<floater
+  positioning="cascading"
+  can_close="true"
+  can_resize="false"
+  can_minimize="false"
+  help_topic="floater_big_preview"
+  layout="topleft"
+  name="floater_big_preview"
+  save_rect="true"
+  single_instance="true"
+  reuse_instance="true"
+  title="PREVIEW"
+  height="465"
+  width="770">
+  <panel
+   height="450"
+   width="750"
+   visible="true"
+   name="big_preview_placeholder"
+   top="5"
+   follows="all"
+   left="10">
+  </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
index 4516c01670..350c385cc3 100644
--- a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
@@ -82,7 +82,7 @@
                 text_color="EmphasisColor"
                 height="14"
                 top_pad="-19"
-                left_pad="-20"
+                left_pad="-30"
                 length="1"
                 halign="center"
                 name="working_lbl"
@@ -92,6 +92,19 @@
                 width="150">
                 Refreshing...
             </text>
+            <button
+                follows="right|top"
+                height="23"
+                label="Big Preview"
+                left="200"
+                top_pad="-19"
+                name="big_preview_btn"
+                tool_tip="Click to open big preview"
+                visible="true"
+                width="100" >
+                <button.commit_callback
+                function="SocialSharing.BigPreview" />
+            </button>
             <text
              length="1"
              follows="top|left|right"
@@ -99,7 +112,7 @@
              height="16"
              left="9"
              name="title_label"
-             top_pad="20"
+             top_pad="15"
              type="string">
               Title:
             </text>
-- 
cgit v1.2.3


From 6dfcd7fc2bd0f502673c43f1a54cda2a8d74e391 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 25 Feb 2014 23:01:52 -0800
Subject: ACME-1327 : WIP : Added computation of the big preview, allow big
 preview to be resizable

---
 indra/newview/llfloaterbigpreview.cpp              |  8 ++--
 indra/newview/llsnapshotlivepreview.cpp            | 54 +++++++++++++++++++++-
 indra/newview/llsnapshotlivepreview.h              | 10 +++-
 .../skins/default/xui/en/floater_big_preview.xml   |  2 +-
 4 files changed, 66 insertions(+), 8 deletions(-)

diff --git a/indra/newview/llfloaterbigpreview.cpp b/indra/newview/llfloaterbigpreview.cpp
index 84a1523e7c..d5f25d5f95 100644
--- a/indra/newview/llfloaterbigpreview.cpp
+++ b/indra/newview/llfloaterbigpreview.cpp
@@ -78,7 +78,7 @@ void LLFloaterBigPreview::draw()
     // Display the preview if one is available
     // HACK!!! We use the puny thumbnail image for the moment
     // *TODO : Use the real large preview
-	if (previewp && previewp->getThumbnailImage())
+	if (previewp && previewp->getBigThumbnailImage())
 	{
 		const LLRect& preview_rect = mPreviewPlaceholder->getRect();
 //		const S32 thumbnail_w = previewp->getThumbnailWidth();
@@ -93,9 +93,7 @@ void LLFloaterBigPreview::draw()
 		// calc preview offset within the floater rect
 		S32 offset_x = preview_rect.mLeft   + local_offset_x;
 		S32 offset_y = preview_rect.mBottom + local_offset_y;
-        
-        //llinfos << "Merov : draw, offset x = " << offset_x  << ", y = " <<  offset_y << ", thumbnail w = " <<  thumbnail_w << ", h = " <<  thumbnail_h << ", rect w = " << preview_rect.getWidth() << ", h = " << preview_rect.getHeight() << llendl;
-        
+                
 		gGL.matrixMode(LLRender::MM_MODELVIEW);
 		// Apply floater transparency to the texture unless the floater is focused.
 		F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
@@ -103,7 +101,7 @@ void LLFloaterBigPreview::draw()
 		gl_draw_scaled_image(offset_x, offset_y,
                              //thumbnail_w, thumbnail_h,
                              preview_rect.getWidth(), preview_rect.getHeight(),
-                             previewp->getThumbnailImage(), color % alpha);
+                             previewp->getBigThumbnailImage(), color % alpha);
 	}
 }
 
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index eef4ed78c8..2ab00419f9 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -75,7 +75,8 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param
 	mColor(1.f, 0.f, 0.f, 0.5f), 
 	mCurImageIndex(0),
 	mPreviewImage(NULL),
-	mThumbnailImage(NULL) ,
+    mThumbnailImage(NULL) ,
+    mBigThumbnailImage(NULL) ,
 	mThumbnailWidth(0),
 	mThumbnailHeight(0),
     mThumbnailSubsampled(FALSE),
@@ -115,6 +116,7 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param
 	mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ;
 	mThumbnailUpdateLock = FALSE ;
 	mThumbnailUpToDate   = FALSE ;
+	mBigThumbnailUpToDate = FALSE ;
 }
 
 LLSnapshotLivePreview::~LLSnapshotLivePreview()
@@ -205,6 +207,7 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail
 	if (new_thumbnail)
 	{
 		mThumbnailUpToDate = FALSE ;
+        mBigThumbnailUpToDate = FALSE;
 	}
 }
 
@@ -602,6 +605,55 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
 	mThumbnailUpdateLock = FALSE ;		
 }
 
+LLViewerTexture* LLSnapshotLivePreview::getBigThumbnailImage()
+{
+	if (mThumbnailUpdateLock) //in the process of updating
+	{
+		return NULL;
+	}
+	if (mBigThumbnailUpToDate && mBigThumbnailImage)//already updated
+	{
+		return mBigThumbnailImage;
+	}
+    
+	LLPointer<LLImageRaw> raw = new LLImageRaw;
+    
+    // The big thumbnail is be a subsampled version of the preview (used in SL Share previews, i.e. Flickr, Twitter, Facebook)
+    raw->resize( mPreviewImage->getWidth(),
+                mPreviewImage->getHeight(),
+                mPreviewImage->getComponents());
+    raw->copy(mPreviewImage);
+    // Scale to the big thumbnail size
+    if (!raw->scale(getBigThumbnailWidth(), getBigThumbnailHeight()))
+    {
+        raw = NULL ;
+    }
+    
+	if (raw)
+	{
+        // Filter
+        // Note: filtering needs to be done *before* the scaling to power of 2 or the effect is distorted
+        if (getFilter() != "")
+        {
+            std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter());
+            if (filter_path != "")
+            {
+                LLImageFilter filter(filter_path);
+                filter.executeFilter(raw);
+            }
+            else
+            {
+                llwarns << "Couldn't find a path to the following filter : " << getFilter() << llendl;
+            }
+        }
+        // Scale to a power of 2 so it can be mapped to a texture
+        raw->expandToPowerOfTwo();
+		mBigThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
+		mBigThumbnailUpToDate = TRUE ;
+	}
+    
+    return mBigThumbnailImage ;
+}
 
 // Called often. Checks whether it's time to grab a new snapshot and if so, does it.
 // Returns TRUE if new snapshot generated, FALSE otherwise.
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index 1b7b5290f8..baf3531e69 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -120,6 +120,11 @@ public:
 	void resetThumbnailImage() { mThumbnailImage = NULL ; }
 	void drawPreviewRect(S32 offset_x, S32 offset_y) ;
 
+    
+	LLViewerTexture* getBigThumbnailImage();
+	S32  getBigThumbnailWidth() const { return 3*mThumbnailWidth ; }
+	S32  getBigThumbnailHeight() const { return 3*mThumbnailHeight ; }
+
 	// Returns TRUE when snapshot generated, FALSE otherwise.
 	static BOOL onIdle( void* snapshot_preview );
 
@@ -145,7 +150,10 @@ private:
 	BOOL                        mThumbnailUpdateLock ;
 	BOOL                        mThumbnailUpToDate ;
 	LLRect                      mThumbnailPlaceholderRect;
-    BOOL                        mThumbnailSubsampled; // TRUE is the thumbnail is a subsampled version of the mPreviewImage
+    BOOL                        mThumbnailSubsampled; // TRUE if the thumbnail is a subsampled version of the mPreviewImage
+    
+	LLPointer<LLViewerTexture>	mBigThumbnailImage ;
+    BOOL                        mBigThumbnailUpToDate;
 
 	S32							mCurImageIndex;
     // The logic is mPreviewImage (raw frame) -> mFormattedImage (formatted / filtered) -> mPreviewImageEncoded (decoded back, to show artifacts)
diff --git a/indra/newview/skins/default/xui/en/floater_big_preview.xml b/indra/newview/skins/default/xui/en/floater_big_preview.xml
index 23698ccc40..c0bdd3d9bd 100644
--- a/indra/newview/skins/default/xui/en/floater_big_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_big_preview.xml
@@ -2,7 +2,7 @@
 <floater
   positioning="cascading"
   can_close="true"
-  can_resize="false"
+  can_resize="true"
   can_minimize="false"
   help_topic="floater_big_preview"
   layout="topleft"
-- 
cgit v1.2.3


From 8fb94a96b18d3b115b75f6d40a06da1c31d21623 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 26 Feb 2014 06:33:15 -0800
Subject: ACME-1327 : WIP : Update the big preview with size and refresh as
 well

---
 indra/newview/llsnapshotlivepreview.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 2ab00419f9..db203c7c78 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -545,6 +545,9 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
 		return ;
 	}
 
+    // Invalidate the big thumbnail when we regenerate the small one
+    mBigThumbnailUpToDate = FALSE;
+
 	if(mThumbnailImage)
 	{
 		resetThumbnailImage() ;
-- 
cgit v1.2.3


From d80a812ffc0e70dcb049aefca69f2a4f8bbd4ab8 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Wed, 26 Feb 2014 20:21:05 +0000
Subject: Changed SLShare photo upload filename to Untitled for the sake of
 default Flickr title

---
 indra/newview/llfacebookconnect.cpp | 2 +-
 indra/newview/llflickrconnect.cpp   | 2 +-
 indra/newview/lltwitterconnect.cpp  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index e3ddb31935..ec7d0f7c50 100644
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -518,7 +518,7 @@ void LLFacebookConnect::sharePhoto(LLPointer<LLImageFormatted> image, const std:
 			<< caption << "\r\n";
 
 	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"image\"; filename=\"snapshot." << imageFormat << "\"\r\n"
+			<< "Content-Disposition: form-data; name=\"image\"; filename=\"Untitled." << imageFormat << "\"\r\n"
 			<< "Content-Type: image/" << imageFormat << "\r\n\r\n";
 
 	// Insert the image data.
diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp
index c09e738a26..1898842478 100644
--- a/indra/newview/llflickrconnect.cpp
+++ b/indra/newview/llflickrconnect.cpp
@@ -401,7 +401,7 @@ void LLFlickrConnect::uploadPhoto(LLPointer<LLImageFormatted> image, const std::
 			<< safety_level << "\r\n";
 
 	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"image\"; filename=\"snapshot." << imageFormat << "\"\r\n"
+			<< "Content-Disposition: form-data; name=\"image\"; filename=\"Untitled." << imageFormat << "\"\r\n"
 			<< "Content-Type: image/" << imageFormat << "\r\n\r\n";
 
 	// Insert the image data.
diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp
index 350da84f69..cfdbca1b81 100644
--- a/indra/newview/lltwitterconnect.cpp
+++ b/indra/newview/lltwitterconnect.cpp
@@ -386,7 +386,7 @@ void LLTwitterConnect::uploadPhoto(LLPointer<LLImageFormatted> image, const std:
 			<< status << "\r\n";
 
 	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"image\"; filename=\"snapshot." << imageFormat << "\"\r\n"
+			<< "Content-Disposition: form-data; name=\"image\"; filename=\"Untitled." << imageFormat << "\"\r\n"
 			<< "Content-Type: image/" << imageFormat << "\r\n\r\n";
 
 	// Insert the image data.
-- 
cgit v1.2.3


From ed38a0aede09f42c4fe7eb4dd53ecd6490d12ca0 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 26 Feb 2014 17:22:16 -0800
Subject: ACME-1327 : WIP : Make rescale of preview isotropic, make preview
 button a toggle

---
 indra/newview/llfloaterbigpreview.cpp              | 33 ++++++++++++----------
 indra/newview/llfloaterbigpreview.h                |  4 +--
 indra/newview/llfloaterflickr.cpp                  | 31 +++++++++++++++-----
 indra/newview/llfloaterflickr.h                    |  1 +
 indra/newview/llsnapshotlivepreview.h              |  1 +
 .../skins/default/xui/en/panel_flickr_photo.xml    |  5 ++--
 6 files changed, 48 insertions(+), 27 deletions(-)

diff --git a/indra/newview/llfloaterbigpreview.cpp b/indra/newview/llfloaterbigpreview.cpp
index d5f25d5f95..b516e9dd01 100644
--- a/indra/newview/llfloaterbigpreview.cpp
+++ b/indra/newview/llfloaterbigpreview.cpp
@@ -28,8 +28,6 @@
 #include "llviewerprecompiledheaders.h"
 
 #include "llfloaterbigpreview.h"
-
-#include "llfloaterreg.h"
 #include "llsnapshotlivepreview.h"
 
 ///////////////////////
@@ -57,7 +55,7 @@ void LLFloaterBigPreview::onCancel()
 
 void LLFloaterBigPreview::closeOnFloaterOwnerClosing(LLFloater* floaterp)
 {
-    if (floaterp == mFloaterOwner)
+    if (isFloaterOwner(floaterp))
     {
         closeFloater();
     }
@@ -76,21 +74,25 @@ void LLFloaterBigPreview::draw()
 	LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
     
     // Display the preview if one is available
-    // HACK!!! We use the puny thumbnail image for the moment
-    // *TODO : Use the real large preview
 	if (previewp && previewp->getBigThumbnailImage())
 	{
+        // Get the preview rect
 		const LLRect& preview_rect = mPreviewPlaceholder->getRect();
-//		const S32 thumbnail_w = previewp->getThumbnailWidth();
-//		const S32 thumbnail_h = previewp->getThumbnailHeight();
         
-		// calc preview offset within the preview rect
-//		const S32 local_offset_x = (preview_rect.getWidth()  - thumbnail_w) / 2 ;
-//		const S32 local_offset_y = (preview_rect.getHeight() - thumbnail_h) / 2 ;
-		const S32 local_offset_x = 0 ;
-		const S32 local_offset_y = 0 ;
+        // Get the preview texture size
+		S32 thumbnail_w = previewp->getBigThumbnailWidth();
+		S32 thumbnail_h = previewp->getBigThumbnailHeight();
+        
+        // Compute the scaling ratio and the size of the final texture in the rect: we want to prevent anisotropic scaling (distorted in x and y)
+        F32 ratio = llmax((F32)(thumbnail_w)/(F32)(preview_rect.getWidth()), (F32)(thumbnail_h)/(F32)(preview_rect.getHeight()));
+        thumbnail_w = (S32)((F32)(thumbnail_w)/ratio);
+        thumbnail_h = (S32)((F32)(thumbnail_h)/ratio);
         
-		// calc preview offset within the floater rect
+		// Compute the preview offset within the preview rect: we want to center that preview in the available rect
+		const S32 local_offset_x = (preview_rect.getWidth()  - thumbnail_w) / 2 ;
+		const S32 local_offset_y = (preview_rect.getHeight() - thumbnail_h) / 2 ;
+        
+		// Compute preview offset within the floater rect
 		S32 offset_x = preview_rect.mLeft   + local_offset_x;
 		S32 offset_y = preview_rect.mBottom + local_offset_y;
                 
@@ -98,9 +100,10 @@ void LLFloaterBigPreview::draw()
 		// Apply floater transparency to the texture unless the floater is focused.
 		F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
 		LLColor4 color = LLColor4::white;
+        
+        // Draw the preview texture
 		gl_draw_scaled_image(offset_x, offset_y,
-                             //thumbnail_w, thumbnail_h,
-                             preview_rect.getWidth(), preview_rect.getHeight(),
+                             thumbnail_w, thumbnail_h,
                              previewp->getBigThumbnailImage(), color % alpha);
 	}
 }
diff --git a/indra/newview/llfloaterbigpreview.h b/indra/newview/llfloaterbigpreview.h
index 91b0968e88..63c6784d36 100644
--- a/indra/newview/llfloaterbigpreview.h
+++ b/indra/newview/llfloaterbigpreview.h
@@ -28,9 +28,6 @@
 #define LL_LLFLOATERBIGPREVIEW_H
 
 #include "llfloater.h"
-#include "llviewertexture.h"
-
-//class LLSnapshotLivePreview;
 
 class LLFloaterBigPreview : public LLFloater
 {
@@ -44,6 +41,7 @@ public:
 
     void setPreview(LLView* previewp) { mPreviewHandle = previewp->getHandle(); }
     void setFloaterOwner(LLFloater* floaterp) { mFloaterOwner = floaterp; }
+    bool isFloaterOwner(LLFloater* floaterp) const { return (mFloaterOwner == floaterp); }
     void closeOnFloaterOwnerClosing(LLFloater* floaterp);
 	
 private:
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 21c619730c..e93adf1570 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -66,6 +66,7 @@ LLFlickrPhotoPanel::LLFlickrPhotoPanel() :
 mSnapshotPanel(NULL),
 mResolutionComboBox(NULL),
 mRefreshBtn(NULL),
+mBtnPreview(NULL),
 mWorkingLabel(NULL),
 mThumbnailPlaceholder(NULL),
 mTitleTextBox(NULL),
@@ -98,6 +99,7 @@ BOOL LLFlickrPhotoPanel::postBuild()
 	mFilterComboBox = getChild<LLUICtrl>("filters_combobox");
 	mFilterComboBox->setCommitCallback(boost::bind(&LLFlickrPhotoPanel::updateResolution, this, TRUE));
 	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
+	mBtnPreview = getChild<LLButton>("big_preview_btn");
     mWorkingLabel = getChild<LLUICtrl>("working_lbl");
 	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
 	mTitleTextBox = getChild<LLUICtrl>("photo_title");
@@ -162,8 +164,14 @@ void LLFlickrPhotoPanel::draw()
     mResolutionComboBox->setEnabled(no_ongoing_connection);
     mFilterComboBox->setEnabled(no_ongoing_connection);
     mRefreshBtn->setEnabled(no_ongoing_connection);
+    mBtnPreview->setEnabled(no_ongoing_connection);
     mLocationCheckbox->setEnabled(no_ongoing_connection);
     
+    // Toggle the button state as appropriate
+	LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
+    bool preview_active = (big_preview_floater && big_preview_floater->getVisible() && big_preview_floater->isFloaterOwner(getParentByType<LLFloater>()));
+	mBtnPreview->setToggleState(preview_active);
+    
     // Display the preview if one is available
 	if (previewp && previewp->getThumbnailImage())
 	{
@@ -256,13 +264,22 @@ void LLFlickrPhotoPanel::onClickNewSnapshot()
 void LLFlickrPhotoPanel::onClickBigPreview()
 {
 	LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
-	if (big_preview_floater)
-	{
-        LLSnapshotLivePreview* previewp = getPreviewView();
-		big_preview_floater->setPreview(previewp);
-        big_preview_floater->setFloaterOwner(getParentByType<LLFloater>());
-	}
-	LLFloaterReg::showInstance("big_preview");
+    bool preview_active = (big_preview_floater && big_preview_floater->getVisible() && big_preview_floater->isFloaterOwner(getParentByType<LLFloater>()));
+    // Toggle the preview
+    if (preview_active)
+    {
+        LLFloaterReg::hideInstance("big_preview");
+    }
+    else
+    {
+        if (big_preview_floater)
+        {
+            LLSnapshotLivePreview* previewp = getPreviewView();
+            big_preview_floater->setPreview(previewp);
+            big_preview_floater->setFloaterOwner(getParentByType<LLFloater>());
+        }
+        LLFloaterReg::showInstance("big_preview");
+    }
 }
 
 void LLFlickrPhotoPanel::onSend()
diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h
index 9fa4a258e2..8a346c3166 100644
--- a/indra/newview/llfloaterflickr.h
+++ b/indra/newview/llfloaterflickr.h
@@ -76,6 +76,7 @@ private:
 	LLUICtrl * mRatingComboBox;
 	LLUICtrl * mPostButton;
 	LLUICtrl * mCancelButton;
+	LLButton * mBtnPreview;
 };
 
 class LLFlickrAccountPanel : public LLPanel
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index baf3531e69..0e918d165e 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -28,6 +28,7 @@
 #define LL_LLSNAPSHOTLIVEPREVIEW_H
 
 #include "llpanelsnapshot.h"
+#include "llviewertexture.h"
 #include "llviewerwindow.h"
 
 class LLImageJPEG;
diff --git a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
index 350c385cc3..8d8ef45c0d 100644
--- a/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_flickr_photo.xml
@@ -95,11 +95,12 @@
             <button
                 follows="right|top"
                 height="23"
-                label="Big Preview"
+                label="Preview"
                 left="200"
                 top_pad="-19"
                 name="big_preview_btn"
-                tool_tip="Click to open big preview"
+                tool_tip="Click to toggle preview"
+                is_toggle="true"
                 visible="true"
                 width="100" >
                 <button.commit_callback
-- 
cgit v1.2.3


From 279e9b0743dfd86f9b40f693349aae9fc1268d35 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Thu, 27 Feb 2014 13:04:23 -0800
Subject: ACME-1327 : Implemented preview in all SL Share panels, switch
 ownership of preview to focused SL Share photo panel

---
 indra/newview/llfloaterfacebook.cpp                | 67 +++++++++++++++++++++-
 indra/newview/llfloaterfacebook.h                  | 11 +++-
 indra/newview/llfloaterflickr.cpp                  | 44 +++++++++-----
 indra/newview/llfloaterflickr.h                    |  6 ++
 indra/newview/llfloatertwitter.cpp                 | 65 +++++++++++++++++++++
 indra/newview/llfloatertwitter.h                   |  9 +++
 .../skins/default/xui/en/panel_facebook_photo.xml  | 16 +++++-
 .../skins/default/xui/en/panel_twitter_photo.xml   | 16 +++++-
 8 files changed, 215 insertions(+), 19 deletions(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index de849b6b3f..5589d4897d 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -34,6 +34,7 @@
 #include "llcheckboxctrl.h"
 #include "llcombobox.h"
 #include "llfacebookconnect.h"
+#include "llfloaterbigpreview.h"
 #include "llfloaterreg.h"
 #include "lliconctrl.h"
 #include "llimagefiltersmanager.h"
@@ -185,15 +186,18 @@ LLFacebookPhotoPanel::LLFacebookPhotoPanel() :
 mSnapshotPanel(NULL),
 mResolutionComboBox(NULL),
 mRefreshBtn(NULL),
+mBtnPreview(NULL),
 mWorkingLabel(NULL),
 mThumbnailPlaceholder(NULL),
 mCaptionTextBox(NULL),
 mLocationCheckbox(NULL),
 mPostButton(NULL),
+mBigPreviewFloater(NULL),
 mQuality(MAX_QUALITY)
 {
 	mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFacebookPhotoPanel::onSend, this));
 	mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFacebookPhotoPanel::onClickNewSnapshot, this));
+	mCommitCallbackRegistrar.add("SocialSharing.BigPreview", boost::bind(&LLFacebookPhotoPanel::onClickBigPreview, this));
 }
 
 LLFacebookPhotoPanel::~LLFacebookPhotoPanel()
@@ -215,12 +219,14 @@ BOOL LLFacebookPhotoPanel::postBuild()
 	mFilterComboBox = getChild<LLUICtrl>("filters_combobox");
 	mFilterComboBox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateResolution, this, TRUE));
 	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
+	mBtnPreview = getChild<LLButton>("big_preview_btn");
     mWorkingLabel = getChild<LLUICtrl>("working_lbl");
 	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
 	mCaptionTextBox = getChild<LLUICtrl>("photo_caption");
 	mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
 	mPostButton = getChild<LLUICtrl>("post_photo_btn");
 	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
+	mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
 
 	// Update filter list
     std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
@@ -272,9 +278,20 @@ void LLFacebookPhotoPanel::draw()
     mResolutionComboBox->setEnabled(no_ongoing_connection);
     mFilterComboBox->setEnabled(no_ongoing_connection);
     mRefreshBtn->setEnabled(no_ongoing_connection);
+    mBtnPreview->setEnabled(no_ongoing_connection);
     mLocationCheckbox->setEnabled(no_ongoing_connection);
+        
+    // Reassign the preview floater if we have the focus and the preview exists
+    if (hasFocus() && isPreviewVisible())
+    {
+        attachPreview();
+    }
+    
+    // Toggle the button state as appropriate
+    bool preview_active = (isPreviewVisible() && mBigPreviewFloater->isFloaterOwner(getParentByType<LLFloater>()));
+	mBtnPreview->setToggleState(preview_active);
     
-    // Display the preview if one is available
+    // Display the thumbnail if one is available
 	if (previewp && previewp->getThumbnailImage())
 	{
 		const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect();
@@ -365,6 +382,35 @@ void LLFacebookPhotoPanel::onClickNewSnapshot()
 	}
 }
 
+void LLFacebookPhotoPanel::onClickBigPreview()
+{
+    // Toggle the preview
+    if (isPreviewVisible())
+    {
+        LLFloaterReg::hideInstance("big_preview");
+    }
+    else
+    {
+        attachPreview();
+        LLFloaterReg::showInstance("big_preview");
+    }
+}
+
+bool LLFacebookPhotoPanel::isPreviewVisible()
+{
+    return (mBigPreviewFloater && mBigPreviewFloater->getVisible());
+}
+
+void LLFacebookPhotoPanel::attachPreview()
+{
+    if (mBigPreviewFloater)
+    {
+        LLSnapshotLivePreview* previewp = getPreviewView();
+        mBigPreviewFloater->setPreview(previewp);
+        mBigPreviewFloater->setFloaterOwner(getParentByType<LLFloater>());
+    }
+}
+
 void LLFacebookPhotoPanel::onSend()
 {
 	LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookPhotoPanel"); // just in case it is already listening
@@ -439,6 +485,10 @@ void LLFacebookPhotoPanel::clearAndClose()
 	if (floater)
 	{
 		floater->closeFloater();
+        if (mBigPreviewFloater)
+        {
+            mBigPreviewFloater->closeOnFloaterOwnerClosing(floater);
+        }
 	}
 }
 
@@ -964,8 +1014,23 @@ LLFloaterFacebook::LLFloaterFacebook(const LLSD& key) : LLFloater(key),
 	mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterFacebook::onCancel, this));
 }
 
+void LLFloaterFacebook::onClose(bool app_quitting)
+{
+    LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
+    if (big_preview_floater)
+    {
+        big_preview_floater->closeOnFloaterOwnerClosing(this);
+    }
+	LLFloater::onClose(app_quitting);
+}
+
 void LLFloaterFacebook::onCancel()
 {
+    LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
+    if (big_preview_floater)
+    {
+        big_preview_floater->closeOnFloaterOwnerClosing(this);
+    }
     closeFloater();
 }
 
diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h
index 20c401d0c1..08c5f24e4d 100644
--- a/indra/newview/llfloaterfacebook.h
+++ b/indra/newview/llfloaterfacebook.h
@@ -35,6 +35,7 @@ class LLIconCtrl;
 class LLCheckBoxCtrl;
 class LLSnapshotLivePreview;
 class LLAvatarList;
+class LLFloaterBigPreview;
 
 class LLFacebookStatusPanel : public LLPanel
 {
@@ -65,6 +66,7 @@ public:
 
 	LLSnapshotLivePreview* getPreviewView();
 	void onVisibilityChange(const LLSD& new_visibility);
+    void onClickBigPreview();
 	void onClickNewSnapshot();
 	void onSend();
 	S32 notify(const LLSD& info);
@@ -79,6 +81,9 @@ public:
 	LLUICtrl* getRefreshBtn();
 
 private:
+    bool isPreviewVisible();
+    void attachPreview();
+    
 	LLHandle<LLView> mPreviewHandle;
 
 	LLUICtrl * mSnapshotPanel;
@@ -90,7 +95,10 @@ private:
 	LLUICtrl * mCaptionTextBox;
 	LLUICtrl * mLocationCheckbox;
 	LLUICtrl * mPostButton;
-	LLUICtrl* mCancelButton;
+	LLUICtrl * mCancelButton;
+	LLButton * mBtnPreview;
+    
+    LLFloaterBigPreview * mBigPreviewFloater;
     
     S32 mQuality;       // Compression quality
 };
@@ -167,6 +175,7 @@ public:
 	LLFloaterFacebook(const LLSD& key);
 	BOOL postBuild();
 	void draw();
+	void onClose(bool app_quitting);
 	void onCancel();
 	
 	void showPhotoPanel();
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index e93adf1570..16aab09396 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -74,6 +74,7 @@ mDescriptionTextBox(NULL),
 mLocationCheckbox(NULL),
 mTagsTextBox(NULL),
 mRatingComboBox(NULL),
+mBigPreviewFloater(NULL),
 mPostButton(NULL)
 {
 	mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFlickrPhotoPanel::onSend, this));
@@ -110,6 +111,7 @@ BOOL LLFlickrPhotoPanel::postBuild()
 	mRatingComboBox = getChild<LLUICtrl>("rating_combobox");
 	mPostButton = getChild<LLUICtrl>("post_photo_btn");
 	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
+	mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
 
 	// Update filter list
     std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
@@ -167,9 +169,14 @@ void LLFlickrPhotoPanel::draw()
     mBtnPreview->setEnabled(no_ongoing_connection);
     mLocationCheckbox->setEnabled(no_ongoing_connection);
     
+    // Reassign the preview floater if we have the focus and the preview exists
+    if (hasFocus() && isPreviewVisible())
+    {
+        attachPreview();
+    }
+    
     // Toggle the button state as appropriate
-	LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
-    bool preview_active = (big_preview_floater && big_preview_floater->getVisible() && big_preview_floater->isFloaterOwner(getParentByType<LLFloater>()));
+    bool preview_active = (isPreviewVisible() && mBigPreviewFloater->isFloaterOwner(getParentByType<LLFloater>()));
 	mBtnPreview->setToggleState(preview_active);
     
     // Display the preview if one is available
@@ -263,25 +270,33 @@ void LLFlickrPhotoPanel::onClickNewSnapshot()
 
 void LLFlickrPhotoPanel::onClickBigPreview()
 {
-	LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
-    bool preview_active = (big_preview_floater && big_preview_floater->getVisible() && big_preview_floater->isFloaterOwner(getParentByType<LLFloater>()));
     // Toggle the preview
-    if (preview_active)
+    if (isPreviewVisible())
     {
         LLFloaterReg::hideInstance("big_preview");
     }
     else
     {
-        if (big_preview_floater)
-        {
-            LLSnapshotLivePreview* previewp = getPreviewView();
-            big_preview_floater->setPreview(previewp);
-            big_preview_floater->setFloaterOwner(getParentByType<LLFloater>());
-        }
+        attachPreview();
         LLFloaterReg::showInstance("big_preview");
     }
 }
 
+bool LLFlickrPhotoPanel::isPreviewVisible()
+{
+    return (mBigPreviewFloater && mBigPreviewFloater->getVisible());
+}
+
+void LLFlickrPhotoPanel::attachPreview()
+{
+    if (mBigPreviewFloater)
+    {
+        LLSnapshotLivePreview* previewp = getPreviewView();
+        mBigPreviewFloater->setPreview(previewp);
+        mBigPreviewFloater->setFloaterOwner(getParentByType<LLFloater>());
+    }
+}
+
 void LLFlickrPhotoPanel::onSend()
 {
 	LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrPhotoPanel"); // just in case it is already listening
@@ -371,12 +386,11 @@ void LLFlickrPhotoPanel::clearAndClose()
 	LLFloater* floater = getParentByType<LLFloater>();
 	if (floater)
 	{
-        LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
-        if (big_preview_floater)
+		floater->closeFloater();
+        if (mBigPreviewFloater)
         {
-            big_preview_floater->closeOnFloaterOwnerClosing(floater);
+            mBigPreviewFloater->closeOnFloaterOwnerClosing(floater);
         }
-		floater->closeFloater();
 	}
 }
 
diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h
index 8a346c3166..7a5453d32a 100644
--- a/indra/newview/llfloaterflickr.h
+++ b/indra/newview/llfloaterflickr.h
@@ -34,6 +34,7 @@
 class LLIconCtrl;
 class LLCheckBoxCtrl;
 class LLSnapshotLivePreview;
+class LLFloaterBigPreview;
 
 class LLFlickrPhotoPanel : public LLPanel
 {
@@ -61,6 +62,9 @@ public:
 	LLUICtrl* getRefreshBtn();
 
 private:
+    bool isPreviewVisible();
+    void attachPreview();
+
 	LLHandle<LLView> mPreviewHandle;
 
 	LLUICtrl * mSnapshotPanel;
@@ -77,6 +81,8 @@ private:
 	LLUICtrl * mPostButton;
 	LLUICtrl * mCancelButton;
 	LLButton * mBtnPreview;
+
+    LLFloaterBigPreview * mBigPreviewFloater;
 };
 
 class LLFlickrAccountPanel : public LLPanel
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index e9db6e01dd..0b2987a3c1 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -34,6 +34,7 @@
 #include "llcheckboxctrl.h"
 #include "llcombobox.h"
 #include "lltwitterconnect.h"
+#include "llfloaterbigpreview.h"
 #include "llfloaterreg.h"
 #include "lliconctrl.h"
 #include "llimagefiltersmanager.h"
@@ -66,16 +67,19 @@ LLTwitterPhotoPanel::LLTwitterPhotoPanel() :
 mSnapshotPanel(NULL),
 mResolutionComboBox(NULL),
 mRefreshBtn(NULL),
+mBtnPreview(NULL),
 mWorkingLabel(NULL),
 mThumbnailPlaceholder(NULL),
 mStatusCounterLabel(NULL),
 mStatusTextBox(NULL),
 mLocationCheckbox(NULL),
 mPhotoCheckbox(NULL),
+mBigPreviewFloater(NULL),
 mPostButton(NULL)
 {
 	mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLTwitterPhotoPanel::onSend, this));
 	mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLTwitterPhotoPanel::onClickNewSnapshot, this));
+	mCommitCallbackRegistrar.add("SocialSharing.BigPreview", boost::bind(&LLTwitterPhotoPanel::onClickBigPreview, this));
 }
 
 LLTwitterPhotoPanel::~LLTwitterPhotoPanel()
@@ -97,6 +101,7 @@ BOOL LLTwitterPhotoPanel::postBuild()
 	mFilterComboBox = getChild<LLUICtrl>("filters_combobox");
 	mFilterComboBox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::updateResolution, this, TRUE));
 	mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
+	mBtnPreview = getChild<LLButton>("big_preview_btn");
     mWorkingLabel = getChild<LLUICtrl>("working_lbl");
 	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
 	mStatusCounterLabel = getChild<LLUICtrl>("status_counter_label");
@@ -108,6 +113,7 @@ BOOL LLTwitterPhotoPanel::postBuild()
 	mPhotoCheckbox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::onAddPhotoToggled, this));
 	mPostButton = getChild<LLUICtrl>("post_photo_btn");
 	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
+	mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
 
 	// Update filter list
     std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
@@ -160,6 +166,7 @@ void LLTwitterPhotoPanel::draw()
     mResolutionComboBox->setEnabled(no_ongoing_connection && photo_checked);
     mFilterComboBox->setEnabled(no_ongoing_connection && photo_checked);
     mRefreshBtn->setEnabled(no_ongoing_connection && photo_checked);
+    mBtnPreview->setEnabled(no_ongoing_connection);
     mLocationCheckbox->setEnabled(no_ongoing_connection);
     mPhotoCheckbox->setEnabled(no_ongoing_connection);
 
@@ -167,6 +174,16 @@ void LLTwitterPhotoPanel::draw()
 	bool add_photo = mPhotoCheckbox->getValue().asBoolean();
 	updateStatusTextLength(false);
 
+    // Reassign the preview floater if we have the focus and the preview exists
+    if (hasFocus() && isPreviewVisible())
+    {
+        attachPreview();
+    }
+    
+    // Toggle the button state as appropriate
+    bool preview_active = (isPreviewVisible() && mBigPreviewFloater->isFloaterOwner(getParentByType<LLFloater>()));
+	mBtnPreview->setToggleState(preview_active);
+    
     // Display the preview if one is available
 	if (previewp && previewp->getThumbnailImage())
 	{
@@ -268,6 +285,35 @@ void LLTwitterPhotoPanel::onClickNewSnapshot()
 	}
 }
 
+void LLTwitterPhotoPanel::onClickBigPreview()
+{
+    // Toggle the preview
+    if (isPreviewVisible())
+    {
+        LLFloaterReg::hideInstance("big_preview");
+    }
+    else
+    {
+        attachPreview();
+        LLFloaterReg::showInstance("big_preview");
+    }
+}
+
+bool LLTwitterPhotoPanel::isPreviewVisible()
+{
+    return (mBigPreviewFloater && mBigPreviewFloater->getVisible());
+}
+
+void LLTwitterPhotoPanel::attachPreview()
+{
+    if (mBigPreviewFloater)
+    {
+        LLSnapshotLivePreview* previewp = getPreviewView();
+        mBigPreviewFloater->setPreview(previewp);
+        mBigPreviewFloater->setFloaterOwner(getParentByType<LLFloater>());
+    }
+}
+
 void LLTwitterPhotoPanel::onSend()
 {
 	LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterPhotoPanel"); // just in case it is already listening
@@ -359,6 +405,10 @@ void LLTwitterPhotoPanel::clearAndClose()
 	if (floater)
 	{
 		floater->closeFloater();
+        if (mBigPreviewFloater)
+        {
+            mBigPreviewFloater->closeOnFloaterOwnerClosing(floater);
+        }
 	}
 }
 
@@ -672,8 +722,23 @@ LLFloaterTwitter::LLFloaterTwitter(const LLSD& key) : LLFloater(key),
 	mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterTwitter::onCancel, this));
 }
 
+void LLFloaterTwitter::onClose(bool app_quitting)
+{
+    LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
+    if (big_preview_floater)
+    {
+        big_preview_floater->closeOnFloaterOwnerClosing(this);
+    }
+	LLFloater::onClose(app_quitting);
+}
+
 void LLFloaterTwitter::onCancel()
 {
+    LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
+    if (big_preview_floater)
+    {
+        big_preview_floater->closeOnFloaterOwnerClosing(this);
+    }
     closeFloater();
 }
 
diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h
index bb88557ad8..659ab7779a 100644
--- a/indra/newview/llfloatertwitter.h
+++ b/indra/newview/llfloatertwitter.h
@@ -34,6 +34,7 @@
 class LLIconCtrl;
 class LLCheckBoxCtrl;
 class LLSnapshotLivePreview;
+class LLFloaterBigPreview;
 
 class LLTwitterPhotoPanel : public LLPanel
 {
@@ -48,6 +49,7 @@ public:
 	void onVisibilityChange(const LLSD& new_visibility);
 	void onAddLocationToggled();
 	void onAddPhotoToggled();
+    void onClickBigPreview();
 	void onClickNewSnapshot();
 	void onSend();
 	S32 notify(const LLSD& info);
@@ -63,6 +65,9 @@ public:
 	LLUICtrl* getRefreshBtn();
 
 private:
+    bool isPreviewVisible();
+    void attachPreview();
+
 	LLHandle<LLView> mPreviewHandle;
 
 	LLUICtrl * mSnapshotPanel;
@@ -77,7 +82,10 @@ private:
 	LLUICtrl * mPhotoCheckbox;
 	LLUICtrl * mPostButton;
 	LLUICtrl * mCancelButton;
+	LLButton * mBtnPreview;
 
+    LLFloaterBigPreview * mBigPreviewFloater;
+    
 	std::string mOldStatusText;
 };
 
@@ -115,6 +123,7 @@ public:
 	LLFloaterTwitter(const LLSD& key);
 	BOOL postBuild();
 	void draw();
+	void onClose(bool app_quitting);
 	void onCancel();
 
 	void showPhotoPanel();
diff --git a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
index 0cde43a20c..1d826fdbe1 100644
--- a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
@@ -86,7 +86,7 @@
                 text_color="EmphasisColor"
                 height="14"
                 top_pad="-19"
-                left_pad="-20"
+                left_pad="-30"
                 length="1"
                 halign="center"
                 name="working_lbl"
@@ -96,6 +96,20 @@
                 width="150">
                 Refreshing...
             </text>
+            <button
+                follows="right|top"
+                height="23"
+                label="Preview"
+                left="200"
+                top_pad="-19"
+                name="big_preview_btn"
+                tool_tip="Click to toggle preview"
+                is_toggle="true"
+                visible="true"
+                width="100" >
+                <button.commit_callback
+                function="SocialSharing.BigPreview" />
+            </button>
             <text
              length="1"
              follows="top|left|right"
diff --git a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
index bcec09ebab..c2be56da21 100644
--- a/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_twitter_photo.xml
@@ -138,7 +138,7 @@
                 text_color="EmphasisColor"
                 height="14"
                 top_pad="-19"
-                left_pad="-20"
+                left_pad="-30"
                 length="1"
                 halign="center"
                 name="working_lbl"
@@ -148,6 +148,20 @@
                 width="150">
                 Refreshing...
             </text>
+              <button
+                  follows="right|top"
+                  height="23"
+                  label="Preview"
+                  left="200"
+                  top_pad="-19"
+                  name="big_preview_btn"
+                  tool_tip="Click to toggle preview"
+                  is_toggle="true"
+                  visible="true"
+                  width="100" >
+                  <button.commit_callback
+                  function="SocialSharing.BigPreview" />
+              </button>
         </layout_panel>
         <layout_panel
           name="photo_button_panel"
-- 
cgit v1.2.3


From ceec7b7efe8f55f3262e07d9a6284dc5b4ab797a Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Thu, 27 Feb 2014 16:03:35 -0800
Subject: ACME-1333 : Allow Facebook panel to be resized, fixed ensuing follow
 positioning issues in all subpanels

---
 indra/newview/skins/default/xui/en/floater_facebook.xml       | 7 +++++--
 indra/newview/skins/default/xui/en/panel_facebook_account.xml | 2 ++
 indra/newview/skins/default/xui/en/panel_facebook_friends.xml | 1 +
 indra/newview/skins/default/xui/en/panel_facebook_photo.xml   | 9 +++++----
 indra/newview/skins/default/xui/en/panel_facebook_place.xml   | 7 ++++---
 indra/newview/skins/default/xui/en/panel_facebook_status.xml  | 7 ++++---
 6 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/floater_facebook.xml b/indra/newview/skins/default/xui/en/floater_facebook.xml
index 544c443c76..4535b9084e 100644
--- a/indra/newview/skins/default/xui/en/floater_facebook.xml
+++ b/indra/newview/skins/default/xui/en/floater_facebook.xml
@@ -2,7 +2,7 @@
 <floater
   positioning="cascading"
   can_close="true"
-  can_resize="false"
+  can_resize="true"
   help_topic="floater_facebook"
   layout="topleft"
   name="floater_facebook"
@@ -10,6 +10,8 @@
   single_instance="true"
   reuse_instance="true"
   title="POST TO FACEBOOK"
+  min_height="501"
+  min_width="304"
   height="482"
   width="304">
   <panel
@@ -28,6 +30,7 @@
      tab_position="top"
      top="7"
      height="437"
+     follows="all"
      halign="center"
      use_highlighting_on_hover="true">
      <panel
@@ -81,7 +84,7 @@
       Error
      </text>
      <loading_indicator
-      follows="left|bottom|right"
+      follows="left|bottom"
       height="24"
       width="24"
       name="connection_loading_indicator"
diff --git a/indra/newview/skins/default/xui/en/panel_facebook_account.xml b/indra/newview/skins/default/xui/en/panel_facebook_account.xml
index f091d2e9b9..abe0a694a4 100644
--- a/indra/newview/skins/default/xui/en/panel_facebook_account.xml
+++ b/indra/newview/skins/default/xui/en/panel_facebook_account.xml
@@ -2,6 +2,7 @@
 	 height="400"
 	 width="304"
 	 layout="topleft"
+    follows="all"
    name="panel_facebook_account">
   <string
       name="facebook_connected"
@@ -34,6 +35,7 @@
    type="string"/>
   <panel
     layout="topleft"
+    follows="left|top"
     name="panel_buttons"
     height="345"
     left="9">
diff --git a/indra/newview/skins/default/xui/en/panel_facebook_friends.xml b/indra/newview/skins/default/xui/en/panel_facebook_friends.xml
index d772dde0c5..07cbd06afa 100644
--- a/indra/newview/skins/default/xui/en/panel_facebook_friends.xml
+++ b/indra/newview/skins/default/xui/en/panel_facebook_friends.xml
@@ -2,6 +2,7 @@
 	 height="400"
 	 width="304"
 	 layout="topleft"
+    follows="all"
    name="panel_facebook_friends">
   <accordion
  background_visible="true"
diff --git a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
index 1d826fdbe1..81f7a7de22 100644
--- a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
@@ -2,6 +2,7 @@
       height="400"
       width="304"
       layout="topleft"
+      follows="all"
       name="panel_facebook_photo">
       <layout_stack
 	   layout="topleft"
@@ -64,7 +65,7 @@
                 visible="true"
                 name="thumbnail_placeholder"
                 top="33"
-                follows="left|top"
+                follows="left|top|right"
                 left="9">
             </panel>
             <button
@@ -122,7 +123,7 @@
               Comment (optional):
             </text>
             <text_editor
-             follows="left|top"
+             follows="left|top|right"
              height="87"
              width="250"
              left="9"
@@ -145,7 +146,7 @@
           name="photo_button_panel"
           height="25">
           <button
-           follows="left|top"
+           follows="left|bottom"
            top="0"
            left="9"
            height="23"
@@ -156,7 +157,7 @@
              function="SocialSharing.SendPhoto" />
           </button>
           <button
-               follows="left|top"
+               follows="left|bottom"
                height="23"
                label="Cancel"
                name="cancel_photo_btn"
diff --git a/indra/newview/skins/default/xui/en/panel_facebook_place.xml b/indra/newview/skins/default/xui/en/panel_facebook_place.xml
index 1eea8f317b..84c87df523 100644
--- a/indra/newview/skins/default/xui/en/panel_facebook_place.xml
+++ b/indra/newview/skins/default/xui/en/panel_facebook_place.xml
@@ -2,6 +2,7 @@
       height="400"
       width="304"
 	  layout="topleft"
+      follows="all"
       name="panel_facebook_place">
       <layout_stack
 	    layout="topleft"
@@ -26,7 +27,7 @@
             Say something about where you are:
           </text>
           <text_editor
-            follows="top|left"
+            follows="top|left|right"
             height="150"
             width="250"
             left="9"
@@ -106,7 +107,7 @@
             name="place_button_panel"
             height="25">
             <button
-              follows="left|top"
+              follows="left|bottom"
               top="0"
               left="9"
               height="23"
@@ -117,7 +118,7 @@
                  function="SocialSharing.SendCheckin" />
             </button>
             <button
-              follows="left|top"
+              follows="left|bottom"
               height="23"
               label="Cancel"
               name="cancel_place_btn"
diff --git a/indra/newview/skins/default/xui/en/panel_facebook_status.xml b/indra/newview/skins/default/xui/en/panel_facebook_status.xml
index 50e15c2e80..480abec558 100644
--- a/indra/newview/skins/default/xui/en/panel_facebook_status.xml
+++ b/indra/newview/skins/default/xui/en/panel_facebook_status.xml
@@ -1,6 +1,7 @@
     <panel
 	 height="400"
 	 width="304"
+     follows="all"
 	 layout="topleft"
      name="panel_facebook_status">
      <layout_stack
@@ -26,7 +27,7 @@
         What's on your mind?
        </text>
        <text_editor
-        follows="left|top"
+        follows="left|top|right"
         height="150"
         width="250"
         left="9"
@@ -41,7 +42,7 @@
        name="status_button_panel"
        height="25">
        <button
-        follows="left|top"
+        follows="left|bottom"
         top="0"
         left="9"
         height="23"
@@ -52,7 +53,7 @@
           function="SocialSharing.SendStatus" />
        </button>
        <button
-        follows="left|top"
+        follows="left|bottom"
         height="23"
         label="Cancel"
         name="cancel_status_btn"
-- 
cgit v1.2.3


From df26597c0d2ddfcc259dd1b8e838164cbd9ff02a Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Fri, 28 Feb 2014 01:49:58 +0000
Subject: Added FB+SL friends list to Friends tab in Facebook floater for
 ACME-1334

---
 indra/newview/llfacebookconnect.cpp                  |  2 +-
 indra/newview/llfloaterfacebook.cpp                  | 20 +++++++++++++++-----
 indra/newview/llfloaterfacebook.h                    |  1 +
 .../skins/default/xui/en/panel_facebook_friends.xml  | 19 ++++++++++++++++++-
 4 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index ec7d0f7c50..d90b649ecd 100644
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -388,7 +388,7 @@ std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, b
     if (regionp)
     {
 		//url = "http://pdp15.lindenlab.com/fbc/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
-        url = regionp->getCapability("FacebookConnect");
+		url = regionp->getCapability("FacebookConnect");
         url += route;
     
         if (include_read_from_master && mReadFromMaster)
diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 5589d4897d..6c2c2428c5 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -750,12 +750,16 @@ void LLFacebookCheckinPanel::clearAndClose()
 ///////////////////////////
 
 LLFacebookFriendsPanel::LLFacebookFriendsPanel() : 
+mSecondLifeFriends(NULL),
 mSuggestedFriends(NULL)
 {
 }
 
 BOOL LLFacebookFriendsPanel::postBuild()
 {
+	mSecondLifeFriends = getChild<LLAvatarList>("second_life_friends");
+	mSecondLifeFriends->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
+	
 	mSuggestedFriends = getChild<LLAvatarList>("suggested_friends");
 	mSuggestedFriends->setContextMenu(&LLPanelPeopleMenus::gSuggestedFriendsContextMenu);
 	
@@ -767,6 +771,8 @@ BOOL LLFacebookFriendsPanel::postBuild()
 bool LLFacebookFriendsPanel::updateSuggestedFriendList()
 {
 	const LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
+	uuid_vec_t& second_life_friends = mSecondLifeFriends->getIDs();
+	second_life_friends.clear();
 	uuid_vec_t& suggested_friends = mSuggestedFriends->getIDs();
 	suggested_friends.clear();
 
@@ -775,19 +781,23 @@ bool LLFacebookFriendsPanel::updateSuggestedFriendList()
 	for (LLSD::array_const_iterator i = friends.beginArray(); i != friends.endArray(); ++i)
 	{
 		LLUUID agent_id = (*i).asUUID();
-		bool second_life_buddy = agent_id.notNull() ? av_tracker.isBuddy(agent_id) : false;
-
-		if(!second_life_buddy)
+		if (agent_id.notNull())
 		{
-			//FB+SL but not SL friend
-			if (agent_id.notNull())
+			bool second_life_buddy = av_tracker.isBuddy(agent_id);
+			if (second_life_buddy)
+			{
+				second_life_friends.push_back(agent_id);
+			}
+			else
 			{
+				//FB+SL but not SL friend
 				suggested_friends.push_back(agent_id);
 			}
 		}
 	}
 
 	//Force a refresh when there aren't any filter matches (prevent displaying content that shouldn't display)
+	mSecondLifeFriends->setDirty(true, !mSecondLifeFriends->filterHasMatches());
 	mSuggestedFriends->setDirty(true, !mSuggestedFriends->filterHasMatches());
 	//showFriendsAccordionsIfNeeded();
 
diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h
index 08c5f24e4d..c13d64a86a 100644
--- a/indra/newview/llfloaterfacebook.h
+++ b/indra/newview/llfloaterfacebook.h
@@ -139,6 +139,7 @@ private:
 	void updateFacebookList(bool visible);
 	bool onConnectedToFacebook(const LLSD& data);
 	
+	LLAvatarList* mSecondLifeFriends;
 	LLAvatarList* mSuggestedFriends;
 };
 
diff --git a/indra/newview/skins/default/xui/en/panel_facebook_friends.xml b/indra/newview/skins/default/xui/en/panel_facebook_friends.xml
index 07cbd06afa..9d5c86c79d 100644
--- a/indra/newview/skins/default/xui/en/panel_facebook_friends.xml
+++ b/indra/newview/skins/default/xui/en/panel_facebook_friends.xml
@@ -15,11 +15,28 @@
    name="friends_accordion"
    right="-2"
    top_pad="2">
+    <accordion_tab
+     layout="topleft"
+     height="173"
+     name="tab_second_life_friends"
+     title="SL friends">
+      <avatar_list
+       ignore_online_status="true"
+       allow_select="true"
+       follows="all"
+       height="173"
+       layout="topleft"
+       left="0"
+       name="second_life_friends"
+       show_permissions_granted="true"
+       top="0"
+       width="307" />
+    </accordion_tab>
     <accordion_tab
      layout="topleft"
      height="173"
      name="tab_suggested_friends"
-     title="People you may want to friend">
+     title="Add these people as SL friends">
       <avatar_list
        ignore_online_status="true"
        allow_select="true"
-- 
cgit v1.2.3


From 261e728327ce72bc582f41cbb231035f0ee1f9b1 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Fri, 28 Feb 2014 02:08:29 +0000
Subject: Made lists only visible when populated in Friends tab in Facebook
 floater for ACME-1334

---
 indra/newview/llfloaterfacebook.cpp | 20 +++++++++++++++++++-
 indra/newview/llfloaterfacebook.h   |  1 +
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 6c2c2428c5..4e6dd002ed 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -51,6 +51,8 @@
 #include "lltabcontainer.h"
 #include "llavatarlist.h"
 #include "llpanelpeoplemenus.h"
+#include "llaccordionctrl.h"
+#include "llaccordionctrltab.h"
 
 static LLRegisterPanelClassWrapper<LLFacebookStatusPanel> t_panel_status("llfacebookstatuspanel");
 static LLRegisterPanelClassWrapper<LLFacebookPhotoPanel> t_panel_photo("llfacebookphotopanel");
@@ -799,11 +801,27 @@ bool LLFacebookFriendsPanel::updateSuggestedFriendList()
 	//Force a refresh when there aren't any filter matches (prevent displaying content that shouldn't display)
 	mSecondLifeFriends->setDirty(true, !mSecondLifeFriends->filterHasMatches());
 	mSuggestedFriends->setDirty(true, !mSuggestedFriends->filterHasMatches());
-	//showFriendsAccordionsIfNeeded();
+	showFriendsAccordionsIfNeeded();
 
 	return false;
 }
 
+void LLFacebookFriendsPanel::showFriendsAccordionsIfNeeded()
+{
+	// Expand and show accordions if needed, else - hide them
+	getChild<LLAccordionCtrlTab>("tab_second_life_friends")->setVisible(mSecondLifeFriends->filterHasMatches());
+	getChild<LLAccordionCtrlTab>("tab_suggested_friends")->setVisible(mSuggestedFriends->filterHasMatches());
+
+	// Rearrange accordions
+	LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion");
+	accordion->arrange();
+
+	// *TODO: new no_matched_tabs_text attribute was implemented in accordion (EXT-7368).
+	// this code should be refactored to use it
+	// keep help text in a synchronization with accordions visibility.
+	//updateFriendListHelpText();
+}
+
 void LLFacebookFriendsPanel::updateFacebookList(bool visible)
 {
 	if (visible)
diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h
index c13d64a86a..16c9e97ff0 100644
--- a/indra/newview/llfloaterfacebook.h
+++ b/indra/newview/llfloaterfacebook.h
@@ -136,6 +136,7 @@ public:
 
 private:
 	bool updateSuggestedFriendList();
+	void showFriendsAccordionsIfNeeded();
 	void updateFacebookList(bool visible);
 	bool onConnectedToFacebook(const LLSD& data);
 	
-- 
cgit v1.2.3


From 209ed601dd6cf9af66eb44d71ab0d28ec94fb81e Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Fri, 28 Feb 2014 13:54:22 -0800
Subject: ACME-1332 : Update the friends lists in the FB Friends panel when
 friend status (add/remove) changes

---
 indra/newview/llfloaterfacebook.cpp | 48 ++++++++++++++++++-------------------
 indra/newview/llfloaterfacebook.h   |  5 +++-
 2 files changed, 28 insertions(+), 25 deletions(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 4e6dd002ed..5acc5260d2 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -757,6 +757,11 @@ mSuggestedFriends(NULL)
 {
 }
 
+LLFacebookFriendsPanel::~LLFacebookFriendsPanel()
+{
+    LLAvatarTracker::instance().removeObserver(this);
+}
+
 BOOL LLFacebookFriendsPanel::postBuild()
 {
 	mSecondLifeFriends = getChild<LLAvatarList>("second_life_friends");
@@ -767,6 +772,8 @@ BOOL LLFacebookFriendsPanel::postBuild()
 	
 	setVisibleCallback(boost::bind(&LLFacebookFriendsPanel::updateFacebookList, this, _2));
 
+    LLAvatarTracker::instance().addObserver(this);
+    
 	return LLPanel::postBuild();
 }
 
@@ -815,42 +822,35 @@ void LLFacebookFriendsPanel::showFriendsAccordionsIfNeeded()
 	// Rearrange accordions
 	LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion");
 	accordion->arrange();
+}
 
-	// *TODO: new no_matched_tabs_text attribute was implemented in accordion (EXT-7368).
-	// this code should be refactored to use it
-	// keep help text in a synchronization with accordions visibility.
-	//updateFriendListHelpText();
+void LLFacebookFriendsPanel::changed(U32 mask)
+{
+	if (mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE))
+	{
+		updateFacebookList(true);
+	}
 }
 
+
 void LLFacebookFriendsPanel::updateFacebookList(bool visible)
 {
 	if (visible)
 	{
-		LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLPanelPeople"); // just in case it is already listening
-		LLEventPumps::instance().obtain("FacebookConnectContent").listen("LLPanelPeople", boost::bind(&LLFacebookFriendsPanel::updateSuggestedFriendList, this));
-
-		LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLPanelPeople"); // just in case it is already listening
-		LLEventPumps::instance().obtain("FacebookConnectState").listen("LLPanelPeople", boost::bind(&LLFacebookFriendsPanel::onConnectedToFacebook, this, _1));
-
-		//Connected
-		if (LLFacebookConnect::instance().isConnected())
-		{
-			LLFacebookConnect::instance().loadFacebookFriends();
-		}
-		//Check if connected
+		// Try to connect to Facebook
         if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) ||
             (LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED))
         {
             LLFacebookConnect::instance().checkConnectionToFacebook();
         }
-
+		// Loads FB friends
+		if (LLFacebookConnect::instance().isConnected())
+		{
+			LLFacebookConnect::instance().loadFacebookFriends();
+		}
+        // Sort the FB friends and update the lists
 		updateSuggestedFriendList();
 	}
-	else
-	{
-		LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLPanelPeople");
-		LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLPanelPeople");
-	}
 }
 
 bool LLFacebookFriendsPanel::onConnectedToFacebook(const LLSD& data)
@@ -861,10 +861,10 @@ bool LLFacebookFriendsPanel::onConnectedToFacebook(const LLSD& data)
 	{
 		LLFacebookConnect::instance().loadFacebookFriends();
 	}
-	else if(connection_state == LLFacebookConnect::FB_NOT_CONNECTED)
+	else if (connection_state == LLFacebookConnect::FB_NOT_CONNECTED)
 	{
 		updateSuggestedFriendList();
-	};
+	}
 
 	return false;
 }
diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h
index 16c9e97ff0..39264c8bff 100644
--- a/indra/newview/llfloaterfacebook.h
+++ b/indra/newview/llfloaterfacebook.h
@@ -27,6 +27,7 @@
 #ifndef LL_LLFLOATERFACEBOOK_H
 #define LL_LLFLOATERFACEBOOK_H
 
+#include "llcallingcard.h"
 #include "llfloater.h"
 #include "lltextbox.h"
 #include "llviewertexture.h"
@@ -128,11 +129,13 @@ private:
     bool mReloadingMapTexture;
 };
 
-class LLFacebookFriendsPanel : public LLPanel
+class LLFacebookFriendsPanel : public LLPanel, public LLFriendObserver
 {
 public:
 	LLFacebookFriendsPanel();
+	~LLFacebookFriendsPanel();
 	BOOL postBuild();
+	virtual void changed(U32 mask);
 
 private:
 	bool updateSuggestedFriendList();
-- 
cgit v1.2.3


From 0fb59172f7c8c2ad2d3f4f77e14108fc16accdc7 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Fri, 28 Feb 2014 16:10:27 -0800
Subject: ACME-1335, ACME-1336 : Add info text to the Friends tab in Facebook
 when no friends are visible

---
 indra/newview/llfloaterfacebook.cpp                | 46 ++++++++++++++++++----
 indra/newview/llfloaterfacebook.h                  |  1 +
 .../default/xui/en/panel_facebook_friends.xml      | 19 +++++++++
 3 files changed, 59 insertions(+), 7 deletions(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 5acc5260d2..9a08f5d581 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -752,6 +752,7 @@ void LLFacebookCheckinPanel::clearAndClose()
 ///////////////////////////
 
 LLFacebookFriendsPanel::LLFacebookFriendsPanel() : 
+mFriendsStatusCaption(NULL),
 mSecondLifeFriends(NULL),
 mSuggestedFriends(NULL)
 {
@@ -764,6 +765,8 @@ LLFacebookFriendsPanel::~LLFacebookFriendsPanel()
 
 BOOL LLFacebookFriendsPanel::postBuild()
 {
+	mFriendsStatusCaption = getChild<LLTextBox>("facebook_friends_status");
+
 	mSecondLifeFriends = getChild<LLAvatarList>("second_life_friends");
 	mSecondLifeFriends->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
 	
@@ -815,13 +818,42 @@ bool LLFacebookFriendsPanel::updateSuggestedFriendList()
 
 void LLFacebookFriendsPanel::showFriendsAccordionsIfNeeded()
 {
-	// Expand and show accordions if needed, else - hide them
-	getChild<LLAccordionCtrlTab>("tab_second_life_friends")->setVisible(mSecondLifeFriends->filterHasMatches());
-	getChild<LLAccordionCtrlTab>("tab_suggested_friends")->setVisible(mSuggestedFriends->filterHasMatches());
-
-	// Rearrange accordions
-	LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion");
-	accordion->arrange();
+    // Show / hide the status text : needs to be done *before* showing / hidding the accordions
+    if (!mSecondLifeFriends->filterHasMatches() && !mSuggestedFriends->filterHasMatches())
+    {
+        // Show some explanation text if the lists are empty...
+        mFriendsStatusCaption->setVisible(true);
+        if (LLFacebookConnect::instance().isConnected())
+        {
+            //...you're connected to FB but have no friends :(
+            mFriendsStatusCaption->setText(getString("facebook_friends_empty"));
+        }
+        else
+        {
+            //...you're not connected to FB
+            mFriendsStatusCaption->setText(getString("facebook_friends_no_connected"));
+        }
+        // Hide the lists
+        getChild<LLAccordionCtrlTab>("friends_accordion")->setVisible(false);
+        getChild<LLAccordionCtrlTab>("tab_second_life_friends")->setVisible(false);
+        getChild<LLAccordionCtrlTab>("tab_suggested_friends")->setVisible(false);
+    }
+    else
+    {
+        // We have something in the lists, hide that
+        mFriendsStatusCaption->setVisible(false);
+        
+        // Show the lists
+        LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion");
+        accordion->setVisible(true);
+        
+        // Expand and show accordions if needed, else - hide them
+        getChild<LLAccordionCtrlTab>("tab_second_life_friends")->setVisible(mSecondLifeFriends->filterHasMatches());
+        getChild<LLAccordionCtrlTab>("tab_suggested_friends")->setVisible(mSuggestedFriends->filterHasMatches());
+        
+        // Rearrange accordions
+        accordion->arrange();
+    }
 }
 
 void LLFacebookFriendsPanel::changed(U32 mask)
diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h
index 39264c8bff..8eff46412d 100644
--- a/indra/newview/llfloaterfacebook.h
+++ b/indra/newview/llfloaterfacebook.h
@@ -143,6 +143,7 @@ private:
 	void updateFacebookList(bool visible);
 	bool onConnectedToFacebook(const LLSD& data);
 	
+	LLTextBox * mFriendsStatusCaption;
 	LLAvatarList* mSecondLifeFriends;
 	LLAvatarList* mSuggestedFriends;
 };
diff --git a/indra/newview/skins/default/xui/en/panel_facebook_friends.xml b/indra/newview/skins/default/xui/en/panel_facebook_friends.xml
index 9d5c86c79d..23820d209a 100644
--- a/indra/newview/skins/default/xui/en/panel_facebook_friends.xml
+++ b/indra/newview/skins/default/xui/en/panel_facebook_friends.xml
@@ -4,6 +4,12 @@
 	 layout="topleft"
     follows="all"
    name="panel_facebook_friends">
+  <string
+   name="facebook_friends_empty"
+   value="You do not have any Facebook friend who are also Second Life resident. You can go to the Status panel and let them know you're in Second Life!" />
+  <string
+   name="facebook_friends_no_connected"
+   value="You're currently not connected to Facebook. Please go to the Account tab to connect and enable this feature." />
   <accordion
  background_visible="true"
  bg_alpha_color="DkGray2"
@@ -50,4 +56,17 @@
        width="307" />
     </accordion_tab>
   </accordion>
+    <text
+        layout="topleft"
+        word_wrap="true"
+        height="64"
+        width="290"
+        follows="top|left|right"
+        font="SansSerif"
+        left="9"
+        name="facebook_friends_status"
+        top="21"
+        type="string">
+        Not connected to Facebook.
+    </text>
 </panel>
-- 
cgit v1.2.3


From 66287bf951485edbba81039f88183a8bce769ad2 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Sun, 2 Mar 2014 18:01:32 -0800
Subject: ACME-1335, ACME-1336 : Add callbacks to FB events so to update the FB
 friend lists in a timely manner

---
 indra/newview/llfloaterfacebook.cpp | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 9a08f5d581..a0b5b3e22d 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -840,7 +840,7 @@ void LLFacebookFriendsPanel::showFriendsAccordionsIfNeeded()
     }
     else
     {
-        // We have something in the lists, hide that
+        // We have something in the lists, hide the explanatory text
         mFriendsStatusCaption->setVisible(false);
         
         // Show the lists
@@ -860,6 +860,7 @@ void LLFacebookFriendsPanel::changed(U32 mask)
 {
 	if (mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE))
 	{
+        LLFacebookConnect::instance().loadFacebookFriends();
 		updateFacebookList(true);
 	}
 }
@@ -869,6 +870,14 @@ void LLFacebookFriendsPanel::updateFacebookList(bool visible)
 {
 	if (visible)
 	{
+        // We want this to be called to fetch the friends list once a connection is established
+		LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookFriendsPanel");
+		LLEventPumps::instance().obtain("FacebookConnectState").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::onConnectedToFacebook, this, _1));
+        
+        // We then want this to be called to update the displayed lists once the list of friends is received
+		LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLFacebookFriendsPanel"); // just in case it is already listening
+		LLEventPumps::instance().obtain("FacebookConnectContent").listen("LLFacebookFriendsPanel", boost::bind(&LLFacebookFriendsPanel::updateSuggestedFriendList, this));
+        
 		// Try to connect to Facebook
         if ((LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_NOT_CONNECTED) ||
             (LLFacebookConnect::instance().getConnectionState() == LLFacebookConnect::FB_CONNECTION_FAILED))
-- 
cgit v1.2.3


From 83c3e37a2693d60c355baeac10eccdfbe30f0771 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Mon, 3 Mar 2014 10:42:26 -0800
Subject: ACME-1336 : Fix message when FB friends list is empty

---
 indra/newview/skins/default/xui/en/panel_facebook_friends.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/skins/default/xui/en/panel_facebook_friends.xml b/indra/newview/skins/default/xui/en/panel_facebook_friends.xml
index 23820d209a..9d21a3a293 100644
--- a/indra/newview/skins/default/xui/en/panel_facebook_friends.xml
+++ b/indra/newview/skins/default/xui/en/panel_facebook_friends.xml
@@ -6,7 +6,7 @@
    name="panel_facebook_friends">
   <string
    name="facebook_friends_empty"
-   value="You do not have any Facebook friend who are also Second Life resident. You can go to the Status panel and let them know you're in Second Life!" />
+   value="You currently do not have any Facebook friends who are also Second Life residents. Ask your Facebook friends to join Second Life today!" />
   <string
    name="facebook_friends_no_connected"
    value="You're currently not connected to Facebook. Please go to the Account tab to connect and enable this feature." />
-- 
cgit v1.2.3


From 013d72cc90d5c038f9cffca28dbd0660a4e05c22 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 4 Mar 2014 11:30:58 -0800
Subject: ACME-1342 : Fix wrong type when getting friends_accordion in
 resources

---
 indra/newview/llfloaterfacebook.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index a0b5b3e22d..c60782cc87 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -834,7 +834,7 @@ void LLFacebookFriendsPanel::showFriendsAccordionsIfNeeded()
             mFriendsStatusCaption->setText(getString("facebook_friends_no_connected"));
         }
         // Hide the lists
-        getChild<LLAccordionCtrlTab>("friends_accordion")->setVisible(false);
+        getChild<LLAccordionCtrl>("friends_accordion")->setVisible(false);
         getChild<LLAccordionCtrlTab>("tab_second_life_friends")->setVisible(false);
         getChild<LLAccordionCtrlTab>("tab_suggested_friends")->setVisible(false);
     }
-- 
cgit v1.2.3


From 3441d3403f43f718d21f441b3bcf87ae183fdd9d Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 4 Mar 2014 14:01:47 -0800
Subject: ACME-1343 : Reset the siz eof the preview texture to be the same as
 the saved snapshot

---
 indra/newview/llsnapshotlivepreview.cpp | 19 ++++++++-----------
 indra/newview/llsnapshotlivepreview.h   |  6 ++++--
 2 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index db203c7c78..d6a034ba15 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -621,19 +621,16 @@ LLViewerTexture* LLSnapshotLivePreview::getBigThumbnailImage()
     
 	LLPointer<LLImageRaw> raw = new LLImageRaw;
     
-    // The big thumbnail is be a subsampled version of the preview (used in SL Share previews, i.e. Flickr, Twitter, Facebook)
-    raw->resize( mPreviewImage->getWidth(),
-                mPreviewImage->getHeight(),
-                mPreviewImage->getComponents());
-    raw->copy(mPreviewImage);
-    // Scale to the big thumbnail size
-    if (!raw->scale(getBigThumbnailWidth(), getBigThumbnailHeight()))
-    {
-        raw = NULL ;
-    }
-    
 	if (raw)
 	{
+        // The big thumbnail is a new filtered version of the preview (used in SL Share previews, i.e. Flickr, Twitter, Facebook)
+        mBigThumbnailWidth = mPreviewImage->getWidth();
+        mBigThumbnailHeight = mPreviewImage->getHeight();
+        raw->resize( mBigThumbnailWidth,
+                     mBigThumbnailHeight,
+                     mPreviewImage->getComponents());
+        raw->copy(mPreviewImage);
+    
         // Filter
         // Note: filtering needs to be done *before* the scaling to power of 2 or the effect is distorted
         if (getFilter() != "")
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index 0e918d165e..7e19f77e26 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -123,8 +123,8 @@ public:
 
     
 	LLViewerTexture* getBigThumbnailImage();
-	S32  getBigThumbnailWidth() const { return 3*mThumbnailWidth ; }
-	S32  getBigThumbnailHeight() const { return 3*mThumbnailHeight ; }
+	S32  getBigThumbnailWidth() const { return mBigThumbnailWidth ; }
+	S32  getBigThumbnailHeight() const { return mBigThumbnailHeight ; }
 
 	// Returns TRUE when snapshot generated, FALSE otherwise.
 	static BOOL onIdle( void* snapshot_preview );
@@ -154,6 +154,8 @@ private:
     BOOL                        mThumbnailSubsampled; // TRUE if the thumbnail is a subsampled version of the mPreviewImage
     
 	LLPointer<LLViewerTexture>	mBigThumbnailImage ;
+    S32                         mBigThumbnailWidth;
+    S32                         mBigThumbnailHeight;
     BOOL                        mBigThumbnailUpToDate;
 
 	S32							mCurImageIndex;
-- 
cgit v1.2.3


From c64e878333ed86c83b0d82c10cc61d4d8d3e8af2 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Thu, 6 Mar 2014 22:18:49 +0000
Subject: Updated hard links for ACME-1306

---
 indra/newview/skins/default/xui/en/panel_facebook_account.xml | 2 +-
 indra/newview/skins/default/xui/en/panel_flickr_account.xml   | 2 +-
 indra/newview/skins/default/xui/en/panel_twitter_account.xml  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/panel_facebook_account.xml b/indra/newview/skins/default/xui/en/panel_facebook_account.xml
index abe0a694a4..122cbfb717 100644
--- a/indra/newview/skins/default/xui/en/panel_facebook_account.xml
+++ b/indra/newview/skins/default/xui/en/panel_facebook_account.xml
@@ -71,7 +71,7 @@
       name="account_learn_more_label"
       top_pad="20"
       type="string">
-      [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share/ta-p/2149711 Learn about posting to Facebook]
+      [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share-Facebook/ta-p/2149711 Learn about posting to Facebook]
     </text>
   </panel>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_flickr_account.xml b/indra/newview/skins/default/xui/en/panel_flickr_account.xml
index 3a38852049..506d2e2f74 100644
--- a/indra/newview/skins/default/xui/en/panel_flickr_account.xml
+++ b/indra/newview/skins/default/xui/en/panel_flickr_account.xml
@@ -69,7 +69,7 @@
       name="account_learn_more_label"
       top_pad="20"
       type="string">
-      [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share/ta-p/2149711 Learn about posting to Flickr]
+      [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share-Flickr/ta-p/2435609 Learn about posting to Flickr]
     </text>
   </panel>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_twitter_account.xml b/indra/newview/skins/default/xui/en/panel_twitter_account.xml
index 4a413bd711..ee4f6396e1 100644
--- a/indra/newview/skins/default/xui/en/panel_twitter_account.xml
+++ b/indra/newview/skins/default/xui/en/panel_twitter_account.xml
@@ -69,7 +69,7 @@
       name="account_learn_more_label"
       top_pad="20"
       type="string">
-      [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share/ta-p/2149711 Learn about posting to Twitter]
+      [http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-Share-Twitter/ta-p/2435453 Learn about posting to Twitter]
     </text>
   </panel>
 </panel>
-- 
cgit v1.2.3


From e1337ce16e1575c544906dfb5c396fa7b517f112 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Mon, 10 Mar 2014 16:01:50 -0700
Subject: MAINT-3555 : Consitency fix after merge of changeset f269634 in
 viewer-acme

---
 indra/newview/llfloaterfacebook.cpp | 10 +++++-----
 indra/newview/llfloaterflickr.cpp   |  4 ++--
 indra/newview/llfloatertwitter.cpp  |  4 ++--
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index c60782cc87..0388f4dca8 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -54,11 +54,11 @@
 #include "llaccordionctrl.h"
 #include "llaccordionctrltab.h"
 
-static LLRegisterPanelClassWrapper<LLFacebookStatusPanel> t_panel_status("llfacebookstatuspanel");
-static LLRegisterPanelClassWrapper<LLFacebookPhotoPanel> t_panel_photo("llfacebookphotopanel");
-static LLRegisterPanelClassWrapper<LLFacebookCheckinPanel> t_panel_checkin("llfacebookcheckinpanel");
-static LLRegisterPanelClassWrapper<LLFacebookFriendsPanel> t_panel_friends("llfacebookfriendspanel");
-static LLRegisterPanelClassWrapper<LLFacebookAccountPanel> t_panel_account("llfacebookaccountpanel");
+static LLPanelInjector<LLFacebookStatusPanel> t_panel_status("llfacebookstatuspanel");
+static LLPanelInjector<LLFacebookPhotoPanel> t_panel_photo("llfacebookphotopanel");
+static LLPanelInjector<LLFacebookCheckinPanel> t_panel_checkin("llfacebookcheckinpanel");
+static LLPanelInjector<LLFacebookFriendsPanel> t_panel_friends("llfacebookfriendspanel");
+static LLPanelInjector<LLFacebookAccountPanel> t_panel_account("llfacebookaccountpanel");
 
 const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
 const std::string DEFAULT_CHECKIN_LOCATION_URL = "http://maps.secondlife.com/";
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 8c4c36538b..2377cd7c92 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -52,8 +52,8 @@
 #include "llviewerparcelmgr.h"
 #include "llviewerregion.h"
 
-static LLRegisterPanelClassWrapper<LLFlickrPhotoPanel> t_panel_photo("llflickrphotopanel");
-static LLRegisterPanelClassWrapper<LLFlickrAccountPanel> t_panel_account("llflickraccountpanel");
+static LLPanelInjector<LLFlickrPhotoPanel> t_panel_photo("llflickrphotopanel");
+static LLPanelInjector<LLFlickrAccountPanel> t_panel_account("llflickraccountpanel");
 
 const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
 const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=flickr&utm_medium=photo&utm_campaign=slshare";
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index 0b2987a3c1..f20d886b7f 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -51,8 +51,8 @@
 #include "lltabcontainer.h"
 #include "lltexteditor.h"
 
-static LLRegisterPanelClassWrapper<LLTwitterPhotoPanel> t_panel_photo("lltwitterphotopanel");
-static LLRegisterPanelClassWrapper<LLTwitterAccountPanel> t_panel_account("lltwitteraccountpanel");
+static LLPanelInjector<LLTwitterPhotoPanel> t_panel_photo("lltwitterphotopanel");
+static LLPanelInjector<LLTwitterAccountPanel> t_panel_account("lltwitteraccountpanel");
 
 const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
 const std::string DEFAULT_PHOTO_LOCATION_URL = "http://maps.secondlife.com/";
-- 
cgit v1.2.3


From de73a3bac4470fc9339568ad1cf4c2af3827c8b8 Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Wed, 12 Mar 2014 22:43:31 +0100
Subject: Omit Flickr machine tags for parcel if unnamed

---
 indra/newview/llfloaterflickr.cpp | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 2377cd7c92..99b275fd0b 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -380,8 +380,14 @@ void LLFlickrPhotoPanel::sendPhoto()
 			std::string parcel_name = LLViewerParcelMgr::getInstance()->getAgentParcelName();
 			std::string region_name = region->getName();
 			
-			tags += llformat(" \"%s:region=%s\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), region_name.c_str());
-			tags += llformat(" \"%s:parcel=%s\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), parcel_name.c_str());
+			if (!region_name.empty())
+			{
+				tags += llformat(" \"%s:region=%s\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), region_name.c_str());
+			}
+			if (!parcel_name.empty())
+			{
+				tags += llformat(" \"%s:parcel=%s\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), parcel_name.c_str());
+			}
 			tags += llformat(" \"%s:x=%d\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), pos_x);
 			tags += llformat(" \"%s:y=%d\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), pos_y);
 			tags += llformat(" \"%s:z=%d\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), pos_z);
-- 
cgit v1.2.3


From 976f09ffc6b2943b4423cc1816d2ec57b7c98f3f Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Fri, 14 Mar 2014 19:07:16 +0100
Subject: Made location checkbox disabled when caption is empty for ACME-1375

---
 indra/newview/llfloaterfacebook.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 0388f4dca8..fccb2799dc 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -281,8 +281,8 @@ void LLFacebookPhotoPanel::draw()
     mFilterComboBox->setEnabled(no_ongoing_connection);
     mRefreshBtn->setEnabled(no_ongoing_connection);
     mBtnPreview->setEnabled(no_ongoing_connection);
-    mLocationCheckbox->setEnabled(no_ongoing_connection);
-        
+    mLocationCheckbox->setEnabled(no_ongoing_connection && !mCaptionTextBox->getValue().asString().empty());
+    
     // Reassign the preview floater if we have the focus and the preview exists
     if (hasFocus() && isPreviewVisible())
     {
@@ -452,7 +452,7 @@ void LLFacebookPhotoPanel::sendPhoto()
 	std::string caption = mCaptionTextBox->getValue().asString();
 
 	// Add the location if required
-	bool add_location = mLocationCheckbox->getValue().asBoolean();
+	bool add_location = (mLocationCheckbox->getEnabled() && mLocationCheckbox->getValue().asBoolean());
 	if (add_location)
 	{
 		// Get the SLURL for the location
-- 
cgit v1.2.3


From 265822ef20d90b0eb84e5b4c9a0847056095023a Mon Sep 17 00:00:00 2001
From: Cho <cho@lindenlab.com>
Date: Sat, 15 Mar 2014 00:57:35 +0100
Subject: Made location checkbox automatically unchecked when caption is empty
 for ACME-1375

---
 indra/newview/llfloaterfacebook.cpp | 22 +++++++++++++++++++---
 indra/newview/llfloaterfacebook.h   |  2 ++
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index fccb2799dc..6abb0aa0cc 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -195,7 +195,8 @@ mCaptionTextBox(NULL),
 mLocationCheckbox(NULL),
 mPostButton(NULL),
 mBigPreviewFloater(NULL),
-mQuality(MAX_QUALITY)
+mQuality(MAX_QUALITY),
+mIncludeLocation(TRUE)
 {
 	mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFacebookPhotoPanel::onSend, this));
 	mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFacebookPhotoPanel::onClickNewSnapshot, this));
@@ -226,6 +227,7 @@ BOOL LLFacebookPhotoPanel::postBuild()
 	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
 	mCaptionTextBox = getChild<LLUICtrl>("photo_caption");
 	mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
+	mLocationCheckbox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateLocationCheckbox, this));
 	mPostButton = getChild<LLUICtrl>("post_photo_btn");
 	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
 	mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
@@ -282,7 +284,16 @@ void LLFacebookPhotoPanel::draw()
     mRefreshBtn->setEnabled(no_ongoing_connection);
     mBtnPreview->setEnabled(no_ongoing_connection);
     mLocationCheckbox->setEnabled(no_ongoing_connection && !mCaptionTextBox->getValue().asString().empty());
-    
+	
+	if (mCaptionTextBox->getValue().asString().empty())
+	{
+		mLocationCheckbox->setValue(FALSE);
+	}
+	else
+	{
+		mLocationCheckbox->setValue(mIncludeLocation);
+	}
+	
     // Reassign the preview floater if we have the focus and the preview exists
     if (hasFocus() && isPreviewVisible())
     {
@@ -452,7 +463,7 @@ void LLFacebookPhotoPanel::sendPhoto()
 	std::string caption = mCaptionTextBox->getValue().asString();
 
 	// Add the location if required
-	bool add_location = (mLocationCheckbox->getEnabled() && mLocationCheckbox->getValue().asBoolean());
+	bool add_location = mLocationCheckbox->getValue().asBoolean();
 	if (add_location)
 	{
 		// Get the SLURL for the location
@@ -571,6 +582,11 @@ void LLFacebookPhotoPanel::updateResolution(BOOL do_update)
 	}
 }
 
+void LLFacebookPhotoPanel::updateLocationCheckbox()
+{
+	mIncludeLocation = mLocationCheckbox->getValue().asBoolean();
+}
+
 void LLFacebookPhotoPanel::checkAspectRatio(S32 index)
 {
 	LLSnapshotLivePreview *previewp = getPreviewView() ;
diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h
index 8eff46412d..5f2d53eaca 100644
--- a/indra/newview/llfloaterfacebook.h
+++ b/indra/newview/llfloaterfacebook.h
@@ -78,6 +78,7 @@ public:
 
 	void updateControls();
 	void updateResolution(BOOL do_update);
+	void updateLocationCheckbox();
 	void checkAspectRatio(S32 index);
 	LLUICtrl* getRefreshBtn();
 
@@ -102,6 +103,7 @@ private:
     LLFloaterBigPreview * mBigPreviewFloater;
     
     S32 mQuality;       // Compression quality
+	bool mIncludeLocation;
 };
 
 class LLFacebookCheckinPanel : public LLPanel
-- 
cgit v1.2.3


From 619aa8e65c2eb81c62accbc87fcf2c85534180ae Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Mon, 17 Mar 2014 18:08:21 -0700
Subject: ACME-1376 : Suppress location checkbox in Facebook Photo panel

---
 indra/newview/llfloaterfacebook.cpp                | 40 +---------------------
 indra/newview/llfloaterfacebook.h                  |  3 --
 .../skins/default/xui/en/panel_facebook_photo.xml  | 10 +-----
 3 files changed, 2 insertions(+), 51 deletions(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 6abb0aa0cc..b421fa0e55 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -192,11 +192,9 @@ mBtnPreview(NULL),
 mWorkingLabel(NULL),
 mThumbnailPlaceholder(NULL),
 mCaptionTextBox(NULL),
-mLocationCheckbox(NULL),
 mPostButton(NULL),
 mBigPreviewFloater(NULL),
-mQuality(MAX_QUALITY),
-mIncludeLocation(TRUE)
+mQuality(MAX_QUALITY)
 {
 	mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFacebookPhotoPanel::onSend, this));
 	mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFacebookPhotoPanel::onClickNewSnapshot, this));
@@ -226,8 +224,6 @@ BOOL LLFacebookPhotoPanel::postBuild()
     mWorkingLabel = getChild<LLUICtrl>("working_lbl");
 	mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
 	mCaptionTextBox = getChild<LLUICtrl>("photo_caption");
-	mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
-	mLocationCheckbox->setCommitCallback(boost::bind(&LLFacebookPhotoPanel::updateLocationCheckbox, this));
 	mPostButton = getChild<LLUICtrl>("post_photo_btn");
 	mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
 	mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
@@ -283,16 +279,6 @@ void LLFacebookPhotoPanel::draw()
     mFilterComboBox->setEnabled(no_ongoing_connection);
     mRefreshBtn->setEnabled(no_ongoing_connection);
     mBtnPreview->setEnabled(no_ongoing_connection);
-    mLocationCheckbox->setEnabled(no_ongoing_connection && !mCaptionTextBox->getValue().asString().empty());
-	
-	if (mCaptionTextBox->getValue().asString().empty())
-	{
-		mLocationCheckbox->setValue(FALSE);
-	}
-	else
-	{
-		mLocationCheckbox->setValue(mIncludeLocation);
-	}
 	
     // Reassign the preview floater if we have the focus and the preview exists
     if (hasFocus() && isPreviewVisible())
@@ -462,25 +448,6 @@ void LLFacebookPhotoPanel::sendPhoto()
 	// Get the caption
 	std::string caption = mCaptionTextBox->getValue().asString();
 
-	// Add the location if required
-	bool add_location = mLocationCheckbox->getValue().asBoolean();
-	if (add_location)
-	{
-		// Get the SLURL for the location
-		LLSLURL slurl;
-		LLAgentUI::buildSLURL(slurl);
-		std::string slurl_string = slurl.getSLURLString();
-
-		// Add query parameters so Google Analytics can track incoming clicks!
-		slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS;
-
-		// Add it to the caption (pretty crude, but we don't have a better option with photos)
-		if (caption.empty())
-			caption = slurl_string;
-		else
-			caption = caption + " " + slurl_string;
-	}
-
 	// Get the image
 	LLSnapshotLivePreview* previewp = getPreviewView();
 	
@@ -582,11 +549,6 @@ void LLFacebookPhotoPanel::updateResolution(BOOL do_update)
 	}
 }
 
-void LLFacebookPhotoPanel::updateLocationCheckbox()
-{
-	mIncludeLocation = mLocationCheckbox->getValue().asBoolean();
-}
-
 void LLFacebookPhotoPanel::checkAspectRatio(S32 index)
 {
 	LLSnapshotLivePreview *previewp = getPreviewView() ;
diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h
index 5f2d53eaca..fd5d3d0635 100644
--- a/indra/newview/llfloaterfacebook.h
+++ b/indra/newview/llfloaterfacebook.h
@@ -78,7 +78,6 @@ public:
 
 	void updateControls();
 	void updateResolution(BOOL do_update);
-	void updateLocationCheckbox();
 	void checkAspectRatio(S32 index);
 	LLUICtrl* getRefreshBtn();
 
@@ -95,7 +94,6 @@ private:
 	LLUICtrl * mWorkingLabel;
 	LLUICtrl * mThumbnailPlaceholder;
 	LLUICtrl * mCaptionTextBox;
-	LLUICtrl * mLocationCheckbox;
 	LLUICtrl * mPostButton;
 	LLUICtrl * mCancelButton;
 	LLButton * mBtnPreview;
@@ -103,7 +101,6 @@ private:
     LLFloaterBigPreview * mBigPreviewFloater;
     
     S32 mQuality;       // Compression quality
-	bool mIncludeLocation;
 };
 
 class LLFacebookCheckinPanel : public LLPanel
diff --git a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
index 81f7a7de22..b5b6dee004 100644
--- a/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
+++ b/indra/newview/skins/default/xui/en/panel_facebook_photo.xml
@@ -123,7 +123,7 @@
               Comment (optional):
             </text>
             <text_editor
-             follows="left|top|right"
+             follows="left|top|right|bottom"
              height="87"
              width="250"
              left="9"
@@ -133,14 +133,6 @@
              type="string"
              word_wrap="true">
             </text_editor>
-            <check_box
-             follows="left|top"
-             initial_value="true"
-             label="Include location in posting"
-             name="add_location_cb"
-              left="9"
-              height="16"
-             top_pad="8"/>
         </layout_panel>
         <layout_panel
           name="photo_button_panel"
-- 
cgit v1.2.3


From 3eb53f5426a710b0403a84bd6849fe48553194eb Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 7 May 2014 07:42:48 -0700
Subject: Fix Windows build issues: change in onVisibility() profile needed to
 percolate to SL Share panels

---
 indra/newview/llfloaterfacebook.cpp | 7 ++-----
 indra/newview/llfloaterfacebook.h   | 4 ++--
 indra/newview/llfloaterflickr.cpp   | 7 ++-----
 indra/newview/llfloaterflickr.h     | 4 ++--
 indra/newview/llfloatertwitter.cpp  | 7 ++-----
 indra/newview/llfloatertwitter.h    | 4 ++--
 6 files changed, 12 insertions(+), 21 deletions(-)

diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index b421fa0e55..9e3f917eae 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -335,9 +335,8 @@ LLSnapshotLivePreview* LLFacebookPhotoPanel::getPreviewView()
 	return previewp;
 }
 
-void LLFacebookPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
+void LLFacebookPhotoPanel::onVisibilityChange(BOOL visible)
 {
-	bool visible = new_visibility.asBoolean();
 	if (visible)
 	{
 		if (mPreviewHandle.get())
@@ -931,10 +930,8 @@ void LLFacebookAccountPanel::draw()
 	LLPanel::draw();
 }
 
-void LLFacebookAccountPanel::onVisibilityChange(const LLSD& new_visibility)
+void LLFacebookAccountPanel::onVisibilityChange(BOOL visible)
 {
-	bool visible = new_visibility.asBoolean();
-
 	if(visible)
 	{
 		LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLFacebookAccountPanel");
diff --git a/indra/newview/llfloaterfacebook.h b/indra/newview/llfloaterfacebook.h
index fd5d3d0635..34356412d6 100644
--- a/indra/newview/llfloaterfacebook.h
+++ b/indra/newview/llfloaterfacebook.h
@@ -66,7 +66,7 @@ public:
 	void draw();
 
 	LLSnapshotLivePreview* getPreviewView();
-	void onVisibilityChange(const LLSD& new_visibility);
+	void onVisibilityChange(BOOL new_visibility);
     void onClickBigPreview();
 	void onClickNewSnapshot();
 	void onSend();
@@ -155,7 +155,7 @@ public:
 	void draw();
 
 private:
-	void onVisibilityChange(const LLSD& new_visibility);
+	void onVisibilityChange(BOOL new_visibility);
 	bool onFacebookConnectStateChange(const LLSD& data);
 	bool onFacebookConnectInfoChange();
 	void onConnect();
diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp
index 99b275fd0b..4e6d98ecfa 100644
--- a/indra/newview/llfloaterflickr.cpp
+++ b/indra/newview/llfloaterflickr.cpp
@@ -226,9 +226,8 @@ LLSnapshotLivePreview* LLFlickrPhotoPanel::getPreviewView()
 	return previewp;
 }
 
-void LLFlickrPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
+void LLFlickrPhotoPanel::onVisibilityChange(BOOL visible)
 {
-	bool visible = new_visibility.asBoolean();
 	if (visible)
 	{
 		if (mPreviewHandle.get())
@@ -563,10 +562,8 @@ void LLFlickrAccountPanel::draw()
 	LLPanel::draw();
 }
 
-void LLFlickrAccountPanel::onVisibilityChange(const LLSD& new_visibility)
+void LLFlickrAccountPanel::onVisibilityChange(BOOL visible)
 {
-	bool visible = new_visibility.asBoolean();
-
 	if(visible)
 	{
 		LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrAccountPanel");
diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h
index 7a5453d32a..ba27c9a3d8 100644
--- a/indra/newview/llfloaterflickr.h
+++ b/indra/newview/llfloaterflickr.h
@@ -47,7 +47,7 @@ public:
 	void draw();
 
 	LLSnapshotLivePreview* getPreviewView();
-	void onVisibilityChange(const LLSD& new_visibility);
+	void onVisibilityChange(BOOL new_visibility);
 	void onClickNewSnapshot();
     void onClickBigPreview();
 	void onSend();
@@ -93,7 +93,7 @@ public:
 	void draw();
 
 private:
-	void onVisibilityChange(const LLSD& new_visibility);
+	void onVisibilityChange(BOOL new_visibility);
 	bool onFlickrConnectStateChange(const LLSD& data);
 	bool onFlickrConnectInfoChange();
 	void onConnect();
diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp
index f20d886b7f..78e9259919 100644
--- a/indra/newview/llfloatertwitter.cpp
+++ b/indra/newview/llfloatertwitter.cpp
@@ -229,9 +229,8 @@ LLSnapshotLivePreview* LLTwitterPhotoPanel::getPreviewView()
 	return previewp;
 }
 
-void LLTwitterPhotoPanel::onVisibilityChange(const LLSD& new_visibility)
+void LLTwitterPhotoPanel::onVisibilityChange(BOOL visible)
 {
-	bool visible = new_visibility.asBoolean();
 	if (visible)
 	{
 		if (mPreviewHandle.get())
@@ -592,10 +591,8 @@ void LLTwitterAccountPanel::draw()
 	LLPanel::draw();
 }
 
-void LLTwitterAccountPanel::onVisibilityChange(const LLSD& new_visibility)
+void LLTwitterAccountPanel::onVisibilityChange(BOOL visible)
 {
-	bool visible = new_visibility.asBoolean();
-
 	if(visible)
 	{
 		LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterAccountPanel");
diff --git a/indra/newview/llfloatertwitter.h b/indra/newview/llfloatertwitter.h
index 659ab7779a..f07ec2ca2f 100644
--- a/indra/newview/llfloatertwitter.h
+++ b/indra/newview/llfloatertwitter.h
@@ -46,7 +46,7 @@ public:
 	void draw();
 
 	LLSnapshotLivePreview* getPreviewView();
-	void onVisibilityChange(const LLSD& new_visibility);
+	void onVisibilityChange(BOOL new_visibility);
 	void onAddLocationToggled();
 	void onAddPhotoToggled();
     void onClickBigPreview();
@@ -97,7 +97,7 @@ public:
 	void draw();
 
 private:
-	void onVisibilityChange(const LLSD& new_visibility);
+	void onVisibilityChange(BOOL new_visibility);
 	bool onTwitterConnectStateChange(const LLSD& data);
 	bool onTwitterConnectInfoChange();
 	void onConnect();
-- 
cgit v1.2.3


From e3e1a527ccbab17e140f91267c847d7e799dbe6f Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 17 Jun 2014 15:12:31 -0700
Subject: DRTVWR-354 : Rewrite Responders for Twitter and Flickr to conform to
 new LLHTTPClient interface. Fix merge error in Facebook connect as well

---
 indra/newview/llfacebookconnect.cpp |  15 ++-
 indra/newview/llflickrconnect.cpp   | 183 ++++++++++++++++++++---------------
 indra/newview/lltwitterconnect.cpp  | 185 +++++++++++++++++++++---------------
 3 files changed, 224 insertions(+), 159 deletions(-)

diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index 1b741ecc0e..28319564e4 100755
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -181,7 +181,7 @@ public:
 
 	/* virtual */ void httpSuccess()
 	{
-		toast_user_for_success();
+		toast_user_for_facebook_success();
 		LL_DEBUGS("FacebookConnect") << "Post successful. " << dumpResponse() << LL_ENDL;
 		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POSTED);
 	}
@@ -327,9 +327,16 @@ public:
 	{
 		if ( HTTP_FOUND == getStatus() )
 		{
-			LL_INFOS() << "Facebook: Info received" << LL_ENDL;
-			LL_DEBUGS("FacebookConnect") << "Getting Facebook info successful. info: " << getContent() << LL_ENDL;
-			LLFacebookConnect::instance().storeInfo(getContent());
+			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
+			if (location.empty())
+			{
+				LL_WARNS("FacebookConnect") << "Missing Location header " << dumpResponse()
+                << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
+			}
+			else
+			{
+				LLFacebookConnect::instance().openFacebookWeb(location);
+			}
 		}
 		else
 		{
diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp
index 1898842478..b715896264 100644
--- a/indra/newview/llflickrconnect.cpp
+++ b/indra/newview/llflickrconnect.cpp
@@ -77,28 +77,36 @@ public:
         LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS);
     }
     
-	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	/* virtual */ void httpSuccess()
 	{
-		if (isGoodStatus(status))
+		LL_DEBUGS("FlickrConnect") << "Connect successful. " << dumpResponse() << LL_ENDL;
+        LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTED);
+	}
+    
+	/* virtual */ void httpFailure()
+	{
+		if ( HTTP_FOUND == getStatus() )
 		{
-			LL_DEBUGS("FlickrConnect") << "Connect successful. content: " << content << LL_ENDL;
-			
-            LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTED);
+			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
+			if (location.empty())
+			{
+				LL_WARNS("FlickrConnect") << "Missing Location header " << dumpResponse()
+                << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
+			}
+			else
+			{
+                LLFlickrConnect::instance().openFlickrWeb(location);
+			}
 		}
-		else if (status != 302)
+		else
 		{
+			LL_WARNS("FlickrConnect") << dumpResponse() << LL_ENDL;
             LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
-            log_flickr_connect_error("Connect", status, reason, content.get("error_code"), content.get("error_description"));
+			const LLSD& content = getContent();
+			log_flickr_connect_error("Connect", getStatus(), getReason(),
+                                      content.get("error_code"), content.get("error_description"));
 		}
 	}
-    
-    void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-    {
-        if (status == 302)
-        {
-            LLFlickrConnect::instance().openFlickrWeb(content["location"]);
-        }
-    }
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -113,33 +121,41 @@ public:
 		LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_POSTING);
 	}
 	
-	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	/* virtual */ void httpSuccess()
 	{
-		if (isGoodStatus(status))
+        toast_user_for_flickr_success();
+		LL_DEBUGS("FlickrConnect") << "Post successful. " << dumpResponse() << LL_ENDL;
+        LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_POSTED);
+	}
+    
+	/* virtual */ void httpFailure()
+	{
+		if ( HTTP_FOUND == getStatus() )
 		{
-            toast_user_for_flickr_success();
-			LL_DEBUGS("FlickrConnect") << "Post successful. content: " << content << LL_ENDL;
-			
-			LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_POSTED);
+			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
+			if (location.empty())
+			{
+				LL_WARNS("FlickrConnect") << "Missing Location header " << dumpResponse()
+                << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
+			}
+			else
+			{
+                LLFlickrConnect::instance().openFlickrWeb(location);
+			}
 		}
-		else if (status == 404)
+		else if ( HTTP_NOT_FOUND == getStatus() )
 		{
 			LLFlickrConnect::instance().connectToFlickr();
 		}
 		else
 		{
+			LL_WARNS("FlickrConnect") << dumpResponse() << LL_ENDL;
             LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_POST_FAILED);
-            log_flickr_connect_error("Share", status, reason, content.get("error_code"), content.get("error_description"));
+			const LLSD& content = getContent();
+			log_flickr_connect_error("Share", getStatus(), getReason(),
+                                      content.get("error_code"), content.get("error_description"));
 		}
 	}
-    
-    void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-    {
-        if (status == 302)
-        {
-            LLFlickrConnect::instance().openFlickrWeb(content["location"]);
-        }
-    }
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -163,24 +179,27 @@ public:
 		LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_NOT_CONNECTED);
 	}
 
-	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	/* virtual */ void httpSuccess()
+	{
+		LL_DEBUGS("FlickrConnect") << "Disconnect successful. " << dumpResponse() << LL_ENDL;
+		setUserDisconnected();
+	}
+    
+	/* virtual */ void httpFailure()
 	{
-		if (isGoodStatus(status)) 
-		{
-			LL_DEBUGS("FlickrConnect") << "Disconnect successful. content: " << content << LL_ENDL;
-			setUserDisconnected();
-
-		}
 		//User not found so already disconnected
-		else if(status == 404)
+		if ( HTTP_NOT_FOUND == getStatus() )
 		{
-			LL_DEBUGS("FlickrConnect") << "Already disconnected. content: " << content << LL_ENDL;
+			LL_DEBUGS("FlickrConnect") << "Already disconnected. " << dumpResponse() << LL_ENDL;
 			setUserDisconnected();
 		}
 		else
 		{
+			LL_WARNS("FlickrConnect") << dumpResponse() << LL_ENDL;
 			LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_DISCONNECT_FAILED);
-            log_flickr_connect_error("Disconnect", status, reason, content.get("error_code"), content.get("error_description"));
+			const LLSD& content = getContent();
+			log_flickr_connect_error("Disconnect", getStatus(), getReason(),
+                                      content.get("error_code"), content.get("error_description"));
 		}
 	}
 };
@@ -197,33 +216,34 @@ public:
 		LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS);
     }
     
-	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	/* virtual */ void httpSuccess()
+	{
+		LL_DEBUGS("FlickrConnect") << "Connect successful. " << dumpResponse() << LL_ENDL;
+        LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTED);
+	}
+    
+	/* virtual */ void httpFailure()
 	{
-		if (isGoodStatus(status))
+		// show the facebook login page if not connected yet
+		if ( HTTP_NOT_FOUND == getStatus() )
 		{
-			LL_DEBUGS("FlickrConnect") << "Connect successful. content: " << content << LL_ENDL;
-            
-            LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTED);
+			LL_DEBUGS("FlickrConnect") << "Not connected. " << dumpResponse() << LL_ENDL;
+			if (mAutoConnect)
+			{
+                LLFlickrConnect::instance().connectToFlickr();
+			}
+			else
+			{
+                LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_NOT_CONNECTED);
+			}
 		}
 		else
 		{
-			// show the flickr login page if not connected yet
-			if (status == 404)
-			{
-				if (mAutoConnect)
-				{
-					LLFlickrConnect::instance().connectToFlickr();
-				}
-				else
-				{
-					LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_NOT_CONNECTED);
-				}
-			}
-            else
-            {
-                LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
-				log_flickr_connect_error("Connected", status, reason, content.get("error_code"), content.get("error_description"));
-            }
+			LL_WARNS("FlickrConnect") << dumpResponse() << LL_ENDL;
+            LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
+			const LLSD& content = getContent();
+			log_flickr_connect_error("Connected", getStatus(), getReason(),
+                                      content.get("error_code"), content.get("error_description"));
 		}
 	}
     
@@ -238,25 +258,34 @@ class LLFlickrInfoResponder : public LLHTTPClient::Responder
 	LOG_CLASS(LLFlickrInfoResponder);
 public:
 
-	virtual void completed(U32 status, const std::string& reason, const LLSD& info)
+	/* virtual */ void httpSuccess()
+	{
+		LL_INFOS("FlickrConnect") << "Flickr: Info received" << LL_ENDL;
+		LL_DEBUGS("FlickrConnect") << "Getting Flickr info successful. " << dumpResponse() << LL_ENDL;
+        LLFlickrConnect::instance().storeInfo(getContent());
+	}
+    
+	/* virtual */ void httpFailure()
 	{
-		if (isGoodStatus(status))
+		if ( HTTP_FOUND == getStatus() )
 		{
-			llinfos << "Flickr: Info received" << llendl;
-			LL_DEBUGS("FlickrConnect") << "Getting Flickr info successful. info: " << info << LL_ENDL;
-			LLFlickrConnect::instance().storeInfo(info);
+			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
+			if (location.empty())
+			{
+				LL_WARNS("FlickrConnect") << "Missing Location header " << dumpResponse()
+                << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
+			}
+			else
+			{
+                LLFlickrConnect::instance().openFlickrWeb(location);
+			}
 		}
 		else
 		{
-			log_flickr_connect_error("Info", status, reason, info.get("error_code"), info.get("error_description"));
-		}
-	}
-
-	void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-	{
-		if (status == 302)
-		{
-			LLFlickrConnect::instance().openFlickrWeb(content["location"]);
+			LL_WARNS("FlickrConnect") << dumpResponse() << LL_ENDL;
+			const LLSD& content = getContent();
+			log_flickr_connect_error("Info", getStatus(), getReason(),
+                                      content.get("error_code"), content.get("error_description"));
 		}
 	}
 };
diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp
index cfdbca1b81..7088558b83 100644
--- a/indra/newview/lltwitterconnect.cpp
+++ b/indra/newview/lltwitterconnect.cpp
@@ -77,28 +77,36 @@ public:
         LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS);
     }
     
-	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	/* virtual */ void httpSuccess()
 	{
-		if (isGoodStatus(status))
+		LL_DEBUGS("TwitterConnect") << "Connect successful. " << dumpResponse() << LL_ENDL;
+        LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTED);
+	}
+    
+	/* virtual */ void httpFailure()
+	{
+		if ( HTTP_FOUND == getStatus() )
 		{
-			LL_DEBUGS("TwitterConnect") << "Connect successful. content: " << content << LL_ENDL;
-			
-            LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTED);
+			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
+			if (location.empty())
+			{
+				LL_WARNS("TwitterConnect") << "Missing Location header " << dumpResponse()
+                << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
+			}
+			else
+			{
+                LLTwitterConnect::instance().openTwitterWeb(location);
+			}
 		}
-		else if (status != 302)
+		else
 		{
-            LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
-            log_twitter_connect_error("Connect", status, reason, content.get("error_code"), content.get("error_description"));
+			LL_WARNS("TwitterConnect") << dumpResponse() << LL_ENDL;
+			LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
+			const LLSD& content = getContent();
+			log_twitter_connect_error("Connect", getStatus(), getReason(),
+									   content.get("error_code"), content.get("error_description"));
 		}
 	}
-    
-    void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-    {
-        if (status == 302)
-        {
-            LLTwitterConnect::instance().openTwitterWeb(content["location"]);
-        }
-    }
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -113,33 +121,41 @@ public:
 		LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_POSTING);
 	}
 	
-	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	/* virtual */ void httpSuccess()
 	{
-		if (isGoodStatus(status))
+        toast_user_for_twitter_success();
+		LL_DEBUGS("TwitterConnect") << "Post successful. " << dumpResponse() << LL_ENDL;
+        LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_POSTED);
+	}
+    
+	/* virtual */ void httpFailure()
+	{
+		if ( HTTP_FOUND == getStatus() )
 		{
-            toast_user_for_twitter_success();
-			LL_DEBUGS("TwitterConnect") << "Post successful. content: " << content << LL_ENDL;
-			
-			LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_POSTED);
+			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
+			if (location.empty())
+			{
+				LL_WARNS("TwitterConnect") << "Missing Location header " << dumpResponse()
+                << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
+			}
+			else
+			{
+                LLTwitterConnect::instance().openTwitterWeb(location);
+			}
 		}
-		else if (status == 404)
+		else if ( HTTP_NOT_FOUND == getStatus() )
 		{
 			LLTwitterConnect::instance().connectToTwitter();
 		}
 		else
 		{
+			LL_WARNS("TwitterConnect") << dumpResponse() << LL_ENDL;
             LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_POST_FAILED);
-            log_twitter_connect_error("Share", status, reason, content.get("error_code"), content.get("error_description"));
+			const LLSD& content = getContent();
+			log_twitter_connect_error("Share", getStatus(), getReason(),
+									   content.get("error_code"), content.get("error_description"));
 		}
 	}
-    
-    void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-    {
-        if (status == 302)
-        {
-            LLTwitterConnect::instance().openTwitterWeb(content["location"]);
-        }
-    }
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -163,24 +179,27 @@ public:
 		LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_NOT_CONNECTED);
 	}
 
-	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	/* virtual */ void httpSuccess()
+	{
+		LL_DEBUGS("TwitterConnect") << "Disconnect successful. " << dumpResponse() << LL_ENDL;
+		setUserDisconnected();
+	}
+    
+	/* virtual */ void httpFailure()
 	{
-		if (isGoodStatus(status)) 
-		{
-			LL_DEBUGS("TwitterConnect") << "Disconnect successful. content: " << content << LL_ENDL;
-			setUserDisconnected();
-
-		}
 		//User not found so already disconnected
-		else if(status == 404)
+		if ( HTTP_NOT_FOUND == getStatus() )
 		{
-			LL_DEBUGS("TwitterConnect") << "Already disconnected. content: " << content << LL_ENDL;
+			LL_DEBUGS("TwitterConnect") << "Already disconnected. " << dumpResponse() << LL_ENDL;
 			setUserDisconnected();
 		}
 		else
 		{
+			LL_WARNS("TwitterConnect") << dumpResponse() << LL_ENDL;
 			LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_DISCONNECT_FAILED);
-            log_twitter_connect_error("Disconnect", status, reason, content.get("error_code"), content.get("error_description"));
+			const LLSD& content = getContent();
+			log_twitter_connect_error("Disconnect", getStatus(), getReason(),
+									   content.get("error_code"), content.get("error_description"));
 		}
 	}
 };
@@ -197,33 +216,34 @@ public:
 		LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS);
     }
     
-	virtual void completed(U32 status, const std::string& reason, const LLSD& content)
+	/* virtual */ void httpSuccess()
+	{
+		LL_DEBUGS("TwitterConnect") << "Connect successful. " << dumpResponse() << LL_ENDL;
+        LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTED);
+	}
+    
+	/* virtual */ void httpFailure()
 	{
-		if (isGoodStatus(status))
+		// show the facebook login page if not connected yet
+		if ( HTTP_NOT_FOUND == getStatus() )
 		{
-			LL_DEBUGS("TwitterConnect") << "Connect successful. content: " << content << LL_ENDL;
-            
-            LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTED);
+			LL_DEBUGS("TwitterConnect") << "Not connected. " << dumpResponse() << LL_ENDL;
+			if (mAutoConnect)
+			{
+                LLTwitterConnect::instance().connectToTwitter();
+			}
+			else
+			{
+                LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_NOT_CONNECTED);
+			}
 		}
 		else
 		{
-			// show the twitter login page if not connected yet
-			if (status == 404)
-			{
-				if (mAutoConnect)
-				{
-					LLTwitterConnect::instance().connectToTwitter();
-				}
-				else
-				{
-					LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_NOT_CONNECTED);
-				}
-			}
-            else
-            {
-                LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
-				log_twitter_connect_error("Connected", status, reason, content.get("error_code"), content.get("error_description"));
-            }
+			LL_WARNS("TwitterConnect") << dumpResponse() << LL_ENDL;
+            LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
+			const LLSD& content = getContent();
+			log_twitter_connect_error("Connected", getStatus(), getReason(),
+									   content.get("error_code"), content.get("error_description"));
 		}
 	}
     
@@ -238,25 +258,34 @@ class LLTwitterInfoResponder : public LLHTTPClient::Responder
 	LOG_CLASS(LLTwitterInfoResponder);
 public:
 
-	virtual void completed(U32 status, const std::string& reason, const LLSD& info)
+	/* virtual */ void httpSuccess()
+	{
+		LL_INFOS("TwitterConnect") << "Twitter: Info received" << LL_ENDL;
+		LL_DEBUGS("TwitterConnect") << "Getting Twitter info successful. " << dumpResponse() << LL_ENDL;
+        LLTwitterConnect::instance().storeInfo(getContent());
+	}
+    
+	/* virtual */ void httpFailure()
 	{
-		if (isGoodStatus(status))
+		if ( HTTP_FOUND == getStatus() )
 		{
-			llinfos << "Twitter: Info received" << llendl;
-			LL_DEBUGS("TwitterConnect") << "Getting Twitter info successful. info: " << info << LL_ENDL;
-			LLTwitterConnect::instance().storeInfo(info);
+			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
+			if (location.empty())
+			{
+				LL_WARNS("TwitterConnect") << "Missing Location header " << dumpResponse()
+                << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
+			}
+			else
+			{
+                LLTwitterConnect::instance().openTwitterWeb(location);
+			}
 		}
 		else
 		{
-			log_twitter_connect_error("Info", status, reason, info.get("error_code"), info.get("error_description"));
-		}
-	}
-
-	void completedHeader(U32 status, const std::string& reason, const LLSD& content)
-	{
-		if (status == 302)
-		{
-			LLTwitterConnect::instance().openTwitterWeb(content["location"]);
+			LL_WARNS("TwitterConnect") << dumpResponse() << LL_ENDL;
+			const LLSD& content = getContent();
+			log_twitter_connect_error("Info", getStatus(), getReason(),
+									   content.get("error_code"), content.get("error_description"));
 		}
 	}
 };
-- 
cgit v1.2.3


From 7d7d04269106d9cd582023df075c4c2f8ea66f1e Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 17 Jun 2014 15:43:51 -0700
Subject: Retropedaling on SH-4030 fix that crashes my viewer on loggin

---
 indra/newview/lltexturefetch.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 14a42dd8dc..9ea46cab68 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -2593,7 +2593,8 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
 
 	S32 desired_size;
 	std::string exten = gDirUtilp->getExtension(url);
-	if (f_type == FTT_SERVER_BAKE)
+	//if (f_type == FTT_SERVER_BAKE)
+    if ((f_type == FTT_SERVER_BAKE) && !url.empty() && !exten.empty() && (LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C))
 	{
 		// SH-4030: This case should be redundant with the following one, just
 		// breaking it out here to clarify that it's intended behavior.
-- 
cgit v1.2.3


From 00b4a71407940a82f779024cc3808812ae1c6fe0 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 23 Jun 2014 13:43:50 -0400
Subject: Added tag 3.7.10-release for changeset 91dae9494b4d

---
 .hgtags | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.hgtags b/.hgtags
index b972d376f7..02e19f6f66 100755
--- a/.hgtags
+++ b/.hgtags
@@ -482,3 +482,4 @@ d029faf69f20a23007f32420a1ac6a3b89a6d441 3.7.6-release
 83959480cb986522d07b151a0c778ab7f920d41b 3.7.7-release
 bba9b3722eea08949e4ff69591f736bf0f808434 3.7.8-release
 a9f2d0cb11f73b06858e6083bb50083becc3f9cd 3.7.9-release
+91dae9494b4d147541c7a01902334ba19a7ec05e 3.7.10-release
-- 
cgit v1.2.3


From c7057ef56efc1cca5683ca22e2ad410198d131e8 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 23 Jun 2014 13:43:50 -0400
Subject: increment viewer version to 3.7.11

---
 indra/newview/VIEWER_VERSION.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index f06fb9e915..584a914c29 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-3.7.10
+3.7.11
-- 
cgit v1.2.3