1 module psd.parse.parser;
2 import psd.parse.sections;
3 import psd.parse.io;
4 import psd;
5 import std.stdio : File;
6 
7 /**
8     Parse a PSD file
9 */
10 PSD parsePSD(Stream stream) {
11     return parsePSDToCtx(stream).psd;
12 }
13 
14 /**
15     Parse a PSD file
16 */
17 PSD parsePSD(string file) {
18     auto f = File(file, "r");
19     scope(exit) f.close();
20     return parsePSD(new FileStream(f));
21 }
22 
23 /**
24     Parse a PSD file
25 */
26 ParserContext parsePSDToCtx(string file) {
27     auto f = File(file, "r");
28     scope(exit) f.close();
29     auto stream = new FileStream(f);
30     writeln("Made a stream.");
31     auto context = parsePSDToCtx(stream);
32     writeln("Parsed");
33 
34     return context;
35 }
36 
37 /**
38     Parse a PSD file
39 */
40 ParserContext parsePSDToCtx(Stream stream) {
41     ParserContext ctx;
42     ctx.stream = stream;
43 
44     // Parse the header
45     parseHeader(ctx);
46     
47     // Parse image resources (need it for layer tags)
48     parseImageResources(ctx);
49     writeln("Parsed image resources.");
50 
51     // Layer & Mask info
52     // This is where the layers we need are!!
53     parseLayerMaskInfo(ctx);
54     writeln("Parsed layer mask info.");
55     
56     return ctx;
57 }
58 
59 /**
60     Parser context
61 */
62 struct ParserContext {
63     /**
64         Parser stream
65     */
66     Stream stream;
67 
68     /**
69         The main output PSD file
70     */
71     PSD psd;
72 
73     /**
74         The image resources
75     */
76     ImageResourceBlock[] imageResources;
77 
78     /**
79         Layer mask information
80     */
81     LayerMaskInfo layerMaskInfo;
82 
83     /**
84         Proxy for stream.read
85     */
86     pragma(inline, true)
87     ubyte[] read(size_t length) {
88         return stream.read(length);
89     }
90 
91     /**
92         Proxy for stream.readValue
93     */
94     pragma(inline, true)
95     T readValue(T)() {
96         return stream.readValue!T;
97     }
98     
99     /**
100         Rounds numToRound up to a multiple of multipleOf
101     */
102     pragma(inline, true)
103 	T roundUpToMultiple(T)(T numToRound, T multipleOf)
104 	{
105 		// make sure that this function is only called for unsigned types, and ensure that we want to round to a power-of-two
106 		//static_assert(util::IsUnsigned<T>::value == true, "T must be an unsigned type.");
107 		//PSD_ASSERT(IsPowerOfTwo(multipleOf), "Expected a power-of-two.");
108 
109 		return (numToRound + (multipleOf - 1u)) & ~(multipleOf - 1u);
110 	}
111 
112     /**
113         Proxy for stream.readValue, but padds the result.
114     */
115     pragma(inline, true)
116     T readPaddedValue(T)(T multipleOf = 2, T addTo = 0) {
117         T value = stream.readValue!T;
118         return cast(T)roundUpToMultiple(value + addTo, multipleOf);
119     }
120 
121     /**
122         Proxy for stream.read
123     */
124     pragma(inline, true)
125     ubyte[] readData(size_t length) {
126         return stream.read(length);
127     }
128 
129 
130     /**
131         Proxy for stream.readStr
132     */
133     pragma(inline, true)
134     string readStr(size_t length) {
135         return stream.readStr(cast(uint)length);
136     }
137 
138 
139     /**
140         Proxy for stream.readPascalStr
141     */
142     pragma(inline, true)
143     string readPascalStr() {
144         return stream.readPascalStr();
145     }
146 
147     /**
148         Proxy for stream.peekStr
149     */
150     pragma(inline, true)
151     string peekStr(size_t length) {
152         return stream.peekStr(cast(uint)length);
153     }
154 
155     /**
156         Proxy for stream.skip
157     */
158     pragma(inline, true)
159     void skip(ptrdiff_t length) {
160         return stream.skip(length);
161     }
162 
163     /**
164         Proxy for stream.seek
165     */
166     pragma(inline, true)
167     void seek(ptrdiff_t position) {
168         return stream.seek(position);
169     }
170 
171     /**
172         Proxy for stream.tell
173     */
174     pragma(inline, true)
175     size_t tell() {
176         return stream.tell();
177     }
178 
179 
180     /**
181         Proxy for stream.size
182     */
183     pragma(inline, true)
184     size_t length() {
185         return stream.length();
186     }
187 }