Mercurial > projects > dwt2
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 } |