image/decoders/icon/qt/nsIconChannel.cpp

changeset 0
6474c204b198
     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 +}

mercurial