]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngHuffmanTables.java
9f60c6c12badf84646dc029e49d5a6de2f866ddd
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / internal / image / PngHuffmanTables.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2011 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.swt.internal.image;
15
16 import java.io.*;
17
18 public class PngHuffmanTables {
19         PngHuffmanTable literalTable;
20         PngHuffmanTable distanceTable;
21
22         static PngHuffmanTable FixedLiteralTable;
23         static PngHuffmanTable FixedDistanceTable;
24
25         static final int LiteralTableSize = 288;
26         static final int[] FixedLiteralLengths = {
27                 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
28                 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
29                 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
30                 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
31                 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
32                 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
33                 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
34                 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
35                 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
36                 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
37                 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7, 7, 7, 7, 7, 7,
38                 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
39         };
40
41         static final int DistanceTableSize = 32;
42         static final int[] FixedDistanceLengths = {
43                 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
44                 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
45         };
46
47         static final int LengthCodeTableSize = 19;
48         static final int[] LengthCodeOrder = {
49                 16, 17, 18, 0, 8, 7, 9, 6, 10, 5,
50                 11, 4, 12, 3, 13, 2, 14, 1, 15
51         };
52
53 static PngHuffmanTables getDynamicTables(PngDecodingDataStream stream) throws IOException {
54         return new PngHuffmanTables(stream);
55 }
56 static PngHuffmanTables getFixedTables() {
57         return new PngHuffmanTables();
58 }
59
60 private PngHuffmanTable getFixedLiteralTable() {
61         if (FixedLiteralTable == null) {
62                 FixedLiteralTable = new PngHuffmanTable(FixedLiteralLengths);
63         }
64         return FixedLiteralTable;
65 }
66
67 private PngHuffmanTable getFixedDistanceTable() {
68         if (FixedDistanceTable == null) {
69                 FixedDistanceTable = new PngHuffmanTable(FixedDistanceLengths);
70         }
71         return FixedDistanceTable;
72 }
73
74 private PngHuffmanTables () {
75         literalTable = getFixedLiteralTable();
76         distanceTable = getFixedDistanceTable();
77 }
78
79 private PngHuffmanTables (PngDecodingDataStream stream) throws IOException {
80         int literals = PngLzBlockReader.FIRST_LENGTH_CODE
81                 + stream.getNextIdatBits(5);
82         int distances = PngLzBlockReader.FIRST_DISTANCE_CODE
83                 + stream.getNextIdatBits(5);
84         int codeLengthCodes = PngLzBlockReader.FIRST_CODE_LENGTH_CODE
85                 + stream.getNextIdatBits(4);
86
87         if (codeLengthCodes > PngLzBlockReader.LAST_CODE_LENGTH_CODE) {
88                 stream.error();
89         }
90
91         /* Tricky, tricky, tricky. The length codes are stored in
92          * a very odd order. (For the order, see the definition of
93          * the static field lengthCodeOrder.) Also, the data may
94          * not contain values for all the codes. It may just contain
95          * values for the first X number of codes. The table should
96          * be of size <LengthCodeTableSize> regardless of the number
97          * of values actually given in the table.
98          */
99         int[] lengthCodes = new int[LengthCodeTableSize];
100         for (int i = 0; i < codeLengthCodes; i++) {
101                 lengthCodes[LengthCodeOrder[i]] = stream.getNextIdatBits(3);
102         }
103         PngHuffmanTable codeLengthsTable = new PngHuffmanTable(lengthCodes);
104
105         int[] literalLengths = readLengths(
106                 stream, literals, codeLengthsTable, LiteralTableSize);
107         int[] distanceLengths = readLengths(
108                 stream, distances, codeLengthsTable, DistanceTableSize);
109
110         literalTable = new PngHuffmanTable(literalLengths);
111         distanceTable = new PngHuffmanTable(distanceLengths);
112 }
113
114 private int [] readLengths (PngDecodingDataStream stream,
115         int numLengths,
116         PngHuffmanTable lengthsTable,
117         int tableSize) throws IOException
118 {
119         int[] lengths = new int[tableSize];
120
121         for (int index = 0; index < numLengths;) {
122                 int value = lengthsTable.getNextValue(stream);
123                 if (value < 16) {
124                         // Literal value
125                         lengths[index] = value;
126                         index++;
127                 } else if (value == 16) {
128                         // Repeat the previous code 3-6 times.
129                         int count = stream.getNextIdatBits(2) + 3;
130                         for (int i = 0; i < count; i++) {
131                                 lengths[index] = lengths [index - 1];
132                                 index++;
133                         }
134                 } else if (value == 17) {
135                         // Repeat 0 3-10 times.
136                         int count = stream.getNextIdatBits(3) + 3;
137                         for (int i = 0; i < count; i++) {
138                                 lengths[index] = 0;
139                                 index++;
140                         }
141                 } else if (value == 18) {
142                         // Repeat 0 11-138 times.
143                         int count = stream.getNextIdatBits(7) + 11;
144                         for (int i = 0; i < count; i++) {
145                                 lengths[index] = 0;
146                                 index++;
147                         }
148                 } else {
149                         stream.error();
150                 }
151         }
152         return lengths;
153 }
154
155 int getNextLiteralValue(PngDecodingDataStream stream) throws IOException {
156         return literalTable.getNextValue(stream);
157 }
158
159 int getNextDistanceValue(PngDecodingDataStream stream) throws IOException {
160         return distanceTable.getNextValue(stream);
161 }
162
163 }