comparison org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngLzBlockReader.d @ 0:6dd524f61e62

add dwt win and basic java stuff
author Frank Benoit <benoit@tionex.de>
date Mon, 02 Mar 2009 14:44:16 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:6dd524f61e62
1 /*******************************************************************************
2 * Copyright (c) 2000, 2006 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module org.eclipse.swt.internal.image.PngLzBlockReader;
14
15 import org.eclipse.swt.internal.image.PngDecodingDataStream;
16 import org.eclipse.swt.internal.image.PngHuffmanTables;
17
18 public class PngLzBlockReader {
19 bool isLastBlock;
20 byte compressionType;
21 int uncompressedBytesRemaining;
22 PngDecodingDataStream stream;
23 PngHuffmanTables huffmanTables;
24
25 byte[] window;
26 int windowIndex;
27 int copyIndex;
28 int copyBytesRemaining;
29
30 static const int UNCOMPRESSED = 0;
31 static const int COMPRESSED_FIXED = 1;
32 static const int COMPRESSED_DYNAMIC = 2;
33
34 static const int END_OF_COMPRESSED_BLOCK = 256;
35 static const int FIRST_LENGTH_CODE = 257;
36 static const int LAST_LENGTH_CODE = 285;
37 static const int FIRST_DISTANCE_CODE = 1;
38 static const int LAST_DISTANCE_CODE = 29;
39 static const int FIRST_CODE_LENGTH_CODE = 4;
40 static const int LAST_CODE_LENGTH_CODE = 19;
41
42 static const int[] lengthBases = [
43 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27,
44 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
45 ];
46 static const int[] extraLengthBits = [
47 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
48 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0,
49 ];
50 static const int[] distanceBases = [
51 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129,
52 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097,
53 6145, 8193, 12289, 16385, 24577,
54 ];
55 static const int[] extraDistanceBits = [
56 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
57 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
58 ];
59
60
61 this(PngDecodingDataStream stream) {
62 this.stream = stream;
63 isLastBlock = false;
64 }
65
66 void setWindowSize(int windowSize) {
67 window = new byte[windowSize];
68 }
69
70 void readNextBlockHeader() {
71 isLastBlock = stream.getNextIdatBit() !is 0;
72 compressionType = cast(byte)(stream.getNextIdatBits(2) & 0xFF);
73 if (compressionType > 2) stream.error();
74
75 if (compressionType is UNCOMPRESSED) {
76 byte b1 = stream.getNextIdatByte();
77 byte b2 = stream.getNextIdatByte();
78 byte b3 = stream.getNextIdatByte();
79 byte b4 = stream.getNextIdatByte();
80 if (b1 !is ~b3 || b2 !is ~b4) stream.error();
81 uncompressedBytesRemaining = (b1 & 0xFF) | ((b2 & 0xFF) << 8);
82 } else if (compressionType is COMPRESSED_DYNAMIC) {
83 huffmanTables = PngHuffmanTables.getDynamicTables(stream);
84 } else {
85 huffmanTables = PngHuffmanTables.getFixedTables();
86 }
87 }
88
89 byte getNextByte() {
90 if (compressionType is UNCOMPRESSED) {
91 if (uncompressedBytesRemaining is 0) {
92 readNextBlockHeader();
93 return getNextByte();
94 }
95 uncompressedBytesRemaining--;
96 return stream.getNextIdatByte();
97 } else {
98 byte value = getNextCompressedByte();
99 if (value is END_OF_COMPRESSED_BLOCK) {
100 if (isLastBlock) stream.error();
101 readNextBlockHeader();
102 return getNextByte();
103 } else {
104 return value;
105 }
106 }
107 }
108
109 private void assertBlockAtEnd() {
110 if (compressionType is UNCOMPRESSED) {
111 if (uncompressedBytesRemaining > 0) stream.error();
112 } else if (copyBytesRemaining > 0 ||
113 (huffmanTables.getNextLiteralValue(stream) !is END_OF_COMPRESSED_BLOCK))
114 {
115 stream.error();
116 }
117 }
118 void assertCompressedDataAtEnd() {
119 assertBlockAtEnd();
120 while (!isLastBlock) {
121 readNextBlockHeader();
122 assertBlockAtEnd();
123 }
124 }
125
126 private byte getNextCompressedByte() {
127 if (copyBytesRemaining > 0) {
128 byte value = window[copyIndex];
129 window[windowIndex] = value;
130 copyBytesRemaining--;
131
132 copyIndex++;
133 windowIndex++;
134 if (copyIndex is window.length) copyIndex = 0;
135 if (windowIndex is window.length) windowIndex = 0;
136
137 return value;
138 }
139
140 int value = huffmanTables.getNextLiteralValue(stream);
141 if (value < END_OF_COMPRESSED_BLOCK) {
142 window[windowIndex] = cast(byte) (value & 0xFF);
143 windowIndex++;
144 if (windowIndex >= window.length) windowIndex = 0;
145 return cast(byte) (value & 0xFF);
146 } else if (value is END_OF_COMPRESSED_BLOCK) {
147 readNextBlockHeader();
148 return getNextByte();
149 } else if (value <= LAST_LENGTH_CODE) {
150 int extraBits = extraLengthBits[value - FIRST_LENGTH_CODE];
151 int length = lengthBases[value - FIRST_LENGTH_CODE];
152 if (extraBits > 0) {
153 length += stream.getNextIdatBits(extraBits);
154 }
155
156 value = huffmanTables.getNextDistanceValue(stream);
157 if (value > LAST_DISTANCE_CODE) stream.error();
158 extraBits = extraDistanceBits[value];
159 int distance = distanceBases[value];
160 if (extraBits > 0) {
161 distance += stream.getNextIdatBits(extraBits);
162 }
163
164 copyIndex = windowIndex - distance;
165 if (copyIndex < 0) copyIndex += window.length;
166
167 copyBytesRemaining = length;
168 return getNextCompressedByte();
169 } else {
170 stream.error();
171 return 0;
172 }
173 }
174
175 }