michael@0: /* vim:set ts=2 sw=2 sts=2 cin et: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "mozilla/Endian.h" michael@0: michael@0: #include "nsMimeTypes.h" michael@0: #include "nsIMIMEService.h" michael@0: michael@0: #include "nsIStringBundle.h" michael@0: michael@0: #include "nsNetUtil.h" michael@0: #include "nsIURL.h" michael@0: michael@0: #include "nsIconChannel.h" michael@0: #include "nsGtkQtIconsConverter.h" michael@0: michael@0: NS_IMPL_ISUPPORTS(nsIconChannel, michael@0: nsIRequest, michael@0: nsIChannel) michael@0: michael@0: static nsresult michael@0: moz_qicon_to_channel(QImage *image, nsIURI *aURI, michael@0: nsIChannel **aChannel) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(image); michael@0: michael@0: int width = image->width(); michael@0: int height = image->height(); michael@0: michael@0: NS_ENSURE_TRUE(height < 256 && width < 256 && height > 0 && width > 0, michael@0: NS_ERROR_UNEXPECTED); michael@0: michael@0: const int n_channels = 4; michael@0: long int buf_size = 2 + n_channels * height * width; michael@0: uint8_t * const buf = (uint8_t*)NS_Alloc(buf_size); michael@0: NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY); michael@0: uint8_t *out = buf; michael@0: michael@0: *(out++) = width; michael@0: *(out++) = height; michael@0: michael@0: const uchar * const pixels = image->bits(); michael@0: int rowextra = image->bytesPerLine() - width * n_channels; michael@0: michael@0: // encode the RGB data and the A data michael@0: const uchar * in = pixels; michael@0: for (int y = 0; y < height; ++y, in += rowextra) { michael@0: for (int x = 0; x < width; ++x) { michael@0: uint8_t r = *(in++); michael@0: uint8_t g = *(in++); michael@0: uint8_t b = *(in++); michael@0: uint8_t a = *(in++); michael@0: #define DO_PREMULTIPLY(c_) uint8_t(uint16_t(c_) * uint16_t(a) / uint16_t(255)) michael@0: #if MOZ_LITTLE_ENDIAN michael@0: *(out++) = DO_PREMULTIPLY(b); michael@0: *(out++) = DO_PREMULTIPLY(g); michael@0: *(out++) = DO_PREMULTIPLY(r); michael@0: *(out++) = a; michael@0: #else michael@0: *(out++) = a; michael@0: *(out++) = DO_PREMULTIPLY(r); michael@0: *(out++) = DO_PREMULTIPLY(g); michael@0: *(out++) = DO_PREMULTIPLY(b); michael@0: #endif michael@0: #undef DO_PREMULTIPLY michael@0: } michael@0: } michael@0: michael@0: NS_ASSERTION(out == buf + buf_size, "size miscalculation"); michael@0: michael@0: nsresult rv; michael@0: nsCOMPtr stream = michael@0: do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: rv = stream->AdoptData((char*)buf, buf_size); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: return NS_NewInputStreamChannel(aChannel, aURI, stream, michael@0: NS_LITERAL_CSTRING(IMAGE_ICON_MS)); michael@0: } michael@0: michael@0: nsresult michael@0: nsIconChannel::Init(nsIURI* aURI) michael@0: { michael@0: michael@0: nsCOMPtr iconURI = do_QueryInterface(aURI); michael@0: NS_ASSERTION(iconURI, "URI is not an nsIMozIconURI"); michael@0: michael@0: nsAutoCString stockIcon; michael@0: iconURI->GetStockIcon(stockIcon); michael@0: michael@0: nsAutoCString iconSizeString; michael@0: iconURI->GetIconSize(iconSizeString); michael@0: michael@0: uint32_t desiredImageSize; michael@0: iconURI->GetImageSize(&desiredImageSize); michael@0: michael@0: nsAutoCString iconStateString; michael@0: iconURI->GetIconState(iconStateString); michael@0: bool disabled = iconStateString.EqualsLiteral("disabled"); michael@0: michael@0: // This is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=662299 michael@0: // Try to find corresponding freedesktop icon and fallback to empty QIcon if failed. michael@0: QIcon icon = QIcon::fromTheme(QString(stockIcon.get()).replace("gtk-", "edit-")); michael@0: QPixmap pixmap = icon.pixmap(desiredImageSize, desiredImageSize, disabled ? QIcon::Disabled : QIcon::Normal); michael@0: michael@0: QImage image = pixmap.toImage(); michael@0: michael@0: return moz_qicon_to_channel(&image, iconURI, michael@0: getter_AddRefs(mRealChannel)); michael@0: }