| 1 | // Copyright (C) 2016 The Qt Company Ltd. | 
| 2 | // Copyright (C) 2016 Alex Char. | 
| 3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only | 
| 4 |  | 
| 5 | #ifndef QICNSHANDLER_P_H | 
| 6 | #define QICNSHANDLER_P_H | 
| 7 |  | 
| 8 | #include <QtGui/qimageiohandler.h> | 
| 9 | #include <QtCore/qlist.h> | 
| 10 |  | 
| 11 | #ifndef QT_NO_DATASTREAM | 
| 12 |  | 
| 13 | #define MAKEOSTYPE(c0,c1,c2,c3) (((quint8)c0 << 24) | ((quint8)c1 << 16) | ((quint8)c2 << 8) | (quint8)c3) | 
| 14 |  | 
| 15 | QT_BEGIN_NAMESPACE | 
| 16 |  | 
| 17 | struct  | 
| 18 | { | 
| 19 |     enum  { | 
| 20 |          = MAKEOSTYPE('i', 'c', 'n', 's'), // Icns container magic | 
| 21 |           = MAKEOSTYPE('T', 'O', 'C', ' '), // Table of contents | 
| 22 |          = MAKEOSTYPE('i', 'c', 'n', 'V'), // Icon Composer version | 
| 23 |         // Legacy: | 
| 24 |          = MAKEOSTYPE('c', 'l', 'u', 't'), // Color look-up table (pre-OS X resources) | 
| 25 |          = MAKEOSTYPE('t', 'i', 'l', 'e'), // Container (icon variants) | 
| 26 |          = MAKEOSTYPE('o', 'v', 'e', 'r'), // Container (icon variants) | 
| 27 |          = MAKEOSTYPE('o', 'p', 'e', 'n'), // Container (icon variants) | 
| 28 |          = MAKEOSTYPE('d', 'r', 'o', 'p'), // Container (icon variants) | 
| 29 |          = MAKEOSTYPE('o', 'd', 'r', 'p'), // Container (icon variants) | 
| 30 |     }; | 
| 31 |  | 
| 32 |     quint32 ; | 
| 33 |     quint32 ; | 
| 34 | }; | 
| 35 |  | 
| 36 | struct ICNSEntry | 
| 37 | { | 
| 38 |     enum Group { | 
| 39 |         GroupUnknown    = 0,   // Default for invalid ones | 
| 40 |         GroupMini       = 'm', // "mini" (16x12) | 
| 41 |         GroupSmall      = 's', // "small" (16x16) | 
| 42 |         GroupLarge      = 'l', // "large" (32x32) | 
| 43 |         GroupHuge       = 'h', // "huge" (48x48) | 
| 44 |         GroupThumbnail  = 't', // "thumbnail" (128x128) | 
| 45 |         GroupPortable   = 'p', // "portable"? (Speculation, used for png/jp2) | 
| 46 |         GroupCompressed = 'c', // "compressed"? (Speculation, used for png/jp2) | 
| 47 |         // Legacy icons: | 
| 48 |         GroupICON       = 'N', // "ICON" (32x32) | 
| 49 |     }; | 
| 50 |     enum Depth { | 
| 51 |         DepthUnknown    = 0,    // Default for invalid or compressed ones | 
| 52 |         DepthMono       = 1, | 
| 53 |         Depth4bit       = 4, | 
| 54 |         Depth8bit       = 8, | 
| 55 |         Depth32bit      = 32 | 
| 56 |     }; | 
| 57 |     enum Flags { | 
| 58 |         Unknown         = 0x0,              // Default for invalid ones | 
| 59 |         IsIcon          = 0x1,              // Contains a raw icon without alpha or compressed icon | 
| 60 |         IsMask          = 0x2,              // Contains alpha mask | 
| 61 |         IconPlusMask    = IsIcon | IsMask   // Contains raw icon and mask combined in one entry (double size) | 
| 62 |     }; | 
| 63 |     enum Format { | 
| 64 |         FormatUnknown   = 0,    // Default for invalid or undetermined ones | 
| 65 |         RawIcon,                // Raw legacy icon, uncompressed | 
| 66 |         RLE24,                  // Raw 32bit icon, data is compressed | 
| 67 |         PNG,                    // Compressed icon in PNG format | 
| 68 |         JP2                     // Compressed icon in JPEG2000 format | 
| 69 |     }; | 
| 70 |  | 
| 71 |     quint32 ostype;     // Real OSType | 
| 72 |     quint32 variant;    // Virtual OSType: a parent container, zero if parent is icns root | 
| 73 |     Group group;        // ASCII character number | 
| 74 |     quint32 width;      // For uncompressed icons only, zero for compressed ones for now | 
| 75 |     quint32 height;     // For uncompressed icons only, zero for compressed ones fow now | 
| 76 |     Depth depth;        // Color depth | 
| 77 |     Flags flags;        // Flags to determine the type of entry | 
| 78 |     Format dataFormat;  // Format of the image data | 
| 79 |     quint32 dataLength; // Length of the image data in bytes | 
| 80 |     qint64 dataOffset;  // Offset from the initial position of the file/device | 
| 81 |  | 
| 82 |     ICNSEntry() : | 
| 83 |         ostype(0), variant(0), group(GroupUnknown), width(0), height(0), depth(DepthUnknown), | 
| 84 |         flags(Unknown), dataFormat(FormatUnknown), dataLength(0), dataOffset(0) | 
| 85 |     { | 
| 86 |     } | 
| 87 | }; | 
| 88 | Q_DECLARE_TYPEINFO(ICNSEntry, Q_RELOCATABLE_TYPE); | 
| 89 |  | 
| 90 | class QICNSHandler : public QImageIOHandler | 
| 91 | { | 
| 92 | public: | 
| 93 |     QICNSHandler(); | 
| 94 |  | 
| 95 |     bool canRead() const override; | 
| 96 |     bool read(QImage *image) override; | 
| 97 |     bool write(const QImage &image) override; | 
| 98 |  | 
| 99 |     bool supportsOption(ImageOption option) const override; | 
| 100 |     QVariant option(ImageOption option) const override; | 
| 101 |  | 
| 102 |     int imageCount() const override; | 
| 103 |     bool jumpToImage(int imageNumber) override; | 
| 104 |     bool jumpToNextImage() override; | 
| 105 |  | 
| 106 |     static bool canRead(QIODevice *device); | 
| 107 |  | 
| 108 | private: | 
| 109 |     bool ensureScanned() const; | 
| 110 |     bool scanDevice(); | 
| 111 |     bool addEntry(const ICNSBlockHeader &, qint64 imgDataOffset, quint32 variant = 0); | 
| 112 |     const ICNSEntry &getIconMask(const ICNSEntry &icon) const; | 
| 113 |  | 
| 114 | private: | 
| 115 |     enum ScanState { | 
| 116 |         ScanError       = -1, | 
| 117 |         ScanNotScanned  = 0, | 
| 118 |         ScanSuccess     = 1, | 
| 119 |     }; | 
| 120 |  | 
| 121 |     int m_currentIconIndex; | 
| 122 |     QList<ICNSEntry> m_icons; | 
| 123 |     QList<ICNSEntry> m_masks; | 
| 124 |     ScanState m_state; | 
| 125 | }; | 
| 126 |  | 
| 127 | QT_END_NAMESPACE | 
| 128 |  | 
| 129 | #endif // QT_NO_DATASTREAM | 
| 130 |  | 
| 131 | #endif /* QICNSHANDLER_P_H */ | 
| 132 |  |