| |   |
| 72 | 72 | |
| 73 | 73 | int decode(QImage *image, const uchar* buffer, int length, |
| 74 | 74 | int *nextFrameDelay, int *loopCount); |
| static void scan(QIODevice *device, QVector<QSize> *imageSizes); |
| static void scan(QIODevice *device, QVector<QSize> *imageSizes, int *loopCount); |
| 76 | 76 | |
| 77 | 77 | bool newFrame; |
| 78 | 78 | bool partialNewFrame; |
| … | … | |
| 646 | 646 | Scans through the data stream defined by \a device and returns the image |
| 647 | 647 | sizes found in the stream in the \a imageSizes vector. |
| 648 | 648 | */ |
| void QGIFFormat::scan(QIODevice *device, QVector<QSize> *imageSizes) |
| void QGIFFormat::scan(QIODevice *device, QVector<QSize> *imageSizes, int *loopCount) |
| 650 | 650 | { |
| 651 | 651 | if (!device) |
| 652 | 652 | return; |
| … | … | |
| 842 | 842 | hold[count] = ch; |
| 843 | 843 | ++count; |
| 844 | 844 | if (count == hold[0] + 1) { |
| state = SkipBlockSize; |
| if (qstrncmp((char*)(hold+1), "NETSCAPE", 8) == 0) |
| state=NetscapeExtensionBlockSize; |
| else |
| state=SkipBlockSize; |
| 846 | 849 | count = 0; |
| 847 | 850 | } |
| 848 | 851 | break; |
| … | … | |
| 858 | 858 | state = SkipBlockSize; |
| 859 | 859 | } |
| 860 | 860 | break; |
| case NetscapeExtensionBlockSize: // fallthrough |
| case NetscapeExtensionBlockSize: |
| blockSize = ch; |
| count = 0; |
| if (blockSize) |
| state = NetscapeExtensionBlock; |
| else |
| state = Introducer; |
| break; |
| case NetscapeExtensionBlock: |
| if (count < 3) |
| hold[count] = ch; |
| count++; |
| if (count == blockSize) { |
| *loopCount = LM(hold[1], hold[2]); |
| state = SkipBlockSize; |
| } |
| break; |
| 862 | 878 | case SkipBlockSize: |
| 863 | 879 | blockSize = ch; |
| 864 | 880 | count = 0; |
| … | … | |
| 890 | 890 | state = Introducer; |
| 891 | 891 | } |
| 892 | 892 | break; |
| case NetscapeExtensionBlock: // fallthrough |
| 894 | 893 | case SkipBlock: |
| 895 | 894 | ++count; |
| 896 | 895 | if (count == blockSize) |
| … | … | |
| 1027 | 1027 | { |
| 1028 | 1028 | gifFormat = new QGIFFormat; |
| 1029 | 1029 | nextDelay = 0; |
| loopCnt = 0; |
| loopCnt = 1; |
| 1031 | 1031 | frameNumber = -1; |
| 1032 | 1032 | scanIsCached = false; |
| 1033 | 1033 | } |
| … | … | |
| 1127 | 1127 | { |
| 1128 | 1128 | if (option == Size) { |
| 1129 | 1129 | if (!scanIsCached) { |
| QGIFFormat::scan(device(), &imageSizes); |
| QGIFFormat::scan(device(), &imageSizes, &loopCnt); |
| 1131 | 1131 | scanIsCached = true; |
| 1132 | 1132 | } |
| 1133 | 1133 | // before the first frame is read, or we have an empty data stream |
| … | … | |
| 1158 | 1158 | int QGifHandler::imageCount() const |
| 1159 | 1159 | { |
| 1160 | 1160 | if (!scanIsCached) { |
| QGIFFormat::scan(device(), &imageSizes); |
| QGIFFormat::scan(device(), &imageSizes, &loopCnt); |
| 1162 | 1162 | scanIsCached = true; |
| 1163 | 1163 | } |
| 1164 | 1164 | return imageSizes.count(); |
| … | … | |
| 1166 | 1166 | |
| 1167 | 1167 | int QGifHandler::loopCount() const |
| 1168 | 1168 | { |
| if (!scanIsCached) { |
| QGIFFormat::scan(device(), &imageSizes, &loopCnt); |
| scanIsCached = true; |
| } |
| 1169 | 1173 | return loopCnt-1; // In GIF, loop count is iteration count, so subtract one |
| 1170 | 1174 | } |
| 1171 | 1175 | |