1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/image/decoders/icon/qt/nsIconChannel.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,119 @@ 1.4 +/* vim:set ts=2 sw=2 sts=2 cin et: */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include <QIcon> 1.10 + 1.11 +#include <stdlib.h> 1.12 +#include <unistd.h> 1.13 + 1.14 +#include "mozilla/Endian.h" 1.15 + 1.16 +#include "nsMimeTypes.h" 1.17 +#include "nsIMIMEService.h" 1.18 + 1.19 +#include "nsIStringBundle.h" 1.20 + 1.21 +#include "nsNetUtil.h" 1.22 +#include "nsIURL.h" 1.23 + 1.24 +#include "nsIconChannel.h" 1.25 +#include "nsGtkQtIconsConverter.h" 1.26 + 1.27 +NS_IMPL_ISUPPORTS(nsIconChannel, 1.28 + nsIRequest, 1.29 + nsIChannel) 1.30 + 1.31 +static nsresult 1.32 +moz_qicon_to_channel(QImage *image, nsIURI *aURI, 1.33 + nsIChannel **aChannel) 1.34 +{ 1.35 + NS_ENSURE_ARG_POINTER(image); 1.36 + 1.37 + int width = image->width(); 1.38 + int height = image->height(); 1.39 + 1.40 + NS_ENSURE_TRUE(height < 256 && width < 256 && height > 0 && width > 0, 1.41 + NS_ERROR_UNEXPECTED); 1.42 + 1.43 + const int n_channels = 4; 1.44 + long int buf_size = 2 + n_channels * height * width; 1.45 + uint8_t * const buf = (uint8_t*)NS_Alloc(buf_size); 1.46 + NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY); 1.47 + uint8_t *out = buf; 1.48 + 1.49 + *(out++) = width; 1.50 + *(out++) = height; 1.51 + 1.52 + const uchar * const pixels = image->bits(); 1.53 + int rowextra = image->bytesPerLine() - width * n_channels; 1.54 + 1.55 + // encode the RGB data and the A data 1.56 + const uchar * in = pixels; 1.57 + for (int y = 0; y < height; ++y, in += rowextra) { 1.58 + for (int x = 0; x < width; ++x) { 1.59 + uint8_t r = *(in++); 1.60 + uint8_t g = *(in++); 1.61 + uint8_t b = *(in++); 1.62 + uint8_t a = *(in++); 1.63 +#define DO_PREMULTIPLY(c_) uint8_t(uint16_t(c_) * uint16_t(a) / uint16_t(255)) 1.64 +#if MOZ_LITTLE_ENDIAN 1.65 + *(out++) = DO_PREMULTIPLY(b); 1.66 + *(out++) = DO_PREMULTIPLY(g); 1.67 + *(out++) = DO_PREMULTIPLY(r); 1.68 + *(out++) = a; 1.69 +#else 1.70 + *(out++) = a; 1.71 + *(out++) = DO_PREMULTIPLY(r); 1.72 + *(out++) = DO_PREMULTIPLY(g); 1.73 + *(out++) = DO_PREMULTIPLY(b); 1.74 +#endif 1.75 +#undef DO_PREMULTIPLY 1.76 + } 1.77 + } 1.78 + 1.79 + NS_ASSERTION(out == buf + buf_size, "size miscalculation"); 1.80 + 1.81 + nsresult rv; 1.82 + nsCOMPtr<nsIStringInputStream> stream = 1.83 + do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv); 1.84 + NS_ENSURE_SUCCESS(rv, rv); 1.85 + 1.86 + rv = stream->AdoptData((char*)buf, buf_size); 1.87 + NS_ENSURE_SUCCESS(rv, rv); 1.88 + 1.89 + return NS_NewInputStreamChannel(aChannel, aURI, stream, 1.90 + NS_LITERAL_CSTRING(IMAGE_ICON_MS)); 1.91 +} 1.92 + 1.93 +nsresult 1.94 +nsIconChannel::Init(nsIURI* aURI) 1.95 +{ 1.96 + 1.97 + nsCOMPtr<nsIMozIconURI> iconURI = do_QueryInterface(aURI); 1.98 + NS_ASSERTION(iconURI, "URI is not an nsIMozIconURI"); 1.99 + 1.100 + nsAutoCString stockIcon; 1.101 + iconURI->GetStockIcon(stockIcon); 1.102 + 1.103 + nsAutoCString iconSizeString; 1.104 + iconURI->GetIconSize(iconSizeString); 1.105 + 1.106 + uint32_t desiredImageSize; 1.107 + iconURI->GetImageSize(&desiredImageSize); 1.108 + 1.109 + nsAutoCString iconStateString; 1.110 + iconURI->GetIconState(iconStateString); 1.111 + bool disabled = iconStateString.EqualsLiteral("disabled"); 1.112 + 1.113 + // This is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=662299 1.114 + // Try to find corresponding freedesktop icon and fallback to empty QIcon if failed. 1.115 + QIcon icon = QIcon::fromTheme(QString(stockIcon.get()).replace("gtk-", "edit-")); 1.116 + QPixmap pixmap = icon.pixmap(desiredImageSize, desiredImageSize, disabled ? QIcon::Disabled : QIcon::Normal); 1.117 + 1.118 + QImage image = pixmap.toImage(); 1.119 + 1.120 + return moz_qicon_to_channel(&image, iconURI, 1.121 + getter_AddRefs(mRealChannel)); 1.122 +}