-
Notifications
You must be signed in to change notification settings - Fork 0
/
Picture.hs
284 lines (251 loc) · 5.5 KB
/
Picture.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
module Mindra.Gloss.Parser.Picture where
import Control.Applicative
import Control.Monad
import Data.Text (Text)
import Data.Void (Void)
import Data.Maybe (fromMaybe)
import Text.Megaparsec (choice, optional, runParser)
import Text.Megaparsec.Char (char, string)
import Text.Megaparsec.Error (ParseErrorBundle)
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import qualified Graphics.Gloss as G
import qualified System.IO.Unsafe as UIO
import qualified Text.Megaparsec.Char.Lexer as L
import qualified Mindra.Gloss.BitmapStore as BitmapStore
import Mindra.Parser.Common (Parser, pFloat, pList, pWhiteSpace, pRGBA, pStringLiteral)
pBlank :: Parser G.Picture
pBlank = G.Blank <$ string "Blank"
pCircle :: Parser G.Picture
pCircle = do
_ <- string "Circle"
pWhiteSpace
f1 <- pFloat
return $ G.Circle f1
pCircleSolid :: Parser G.Picture
pCircleSolid = do
_ <- string "CircleSolid"
pWhiteSpace
f1 <- pFloat
return $ G.circleSolid f1
pThickCircle :: Parser G.Picture
pThickCircle = do
_ <- string "ThickCircle"
pWhiteSpace
f1 <- pFloat
pWhiteSpace
f2 <- pFloat
return $ G.ThickCircle f1 f2
pArc :: Parser G.Picture
pArc = do
_ <- string "Arc"
pWhiteSpace
f1 <- pFloat
pWhiteSpace
f2 <- pFloat
pWhiteSpace
f3 <- pFloat
return $ G.Arc f1 f2 f3
pArcSolid :: Parser G.Picture
pArcSolid = do
_ <- string "ArcSolid"
pWhiteSpace
f1 <- pFloat
pWhiteSpace
f2 <- pFloat
pWhiteSpace
f3 <- pFloat
return $ G.arcSolid f1 f2 f3
pThickArc :: Parser G.Picture
pThickArc = do
_ <- string "ThickArc"
pWhiteSpace
f1 <- pFloat
pWhiteSpace
f2 <- pFloat
pWhiteSpace
f3 <- pFloat
pWhiteSpace
f4 <- pFloat
return $ G.ThickArc f1 f2 f3 f4
pRectangleSolid :: Parser G.Picture
pRectangleSolid = do
_ <- string "RectangleSolid"
pWhiteSpace
f1 <- pFloat
pWhiteSpace
f2 <- pFloat
return $ G.rectangleSolid f1 f2
pRectangleUpperWire :: Parser G.Picture
pRectangleUpperWire = do
_ <- string "RectangleUpperWire"
pWhiteSpace
f1 <- pFloat
pWhiteSpace
f2 <- pFloat
return $ G.rectangleUpperWire f1 f2
pRectangleUpperSolid :: Parser G.Picture
pRectangleUpperSolid = do
_ <- string "RectangleUpperSolid"
pWhiteSpace
f1 <- pFloat
pWhiteSpace
f2 <- pFloat
return $ G.rectangleUpperSolid f1 f2
pRectangleWire :: Parser G.Picture
pRectangleWire = do
_ <- string "RectangleWire"
pWhiteSpace
f1 <- pFloat
pWhiteSpace
f2 <- pFloat
return $ G.rectangleWire f1 f2
pSectorWire :: Parser G.Picture
pSectorWire = do
_ <- string "SectorWire"
pWhiteSpace
f1 <- pFloat
pWhiteSpace
f2 <- pFloat
pWhiteSpace
f3 <- pFloat
return $ G.sectorWire f1 f2 f3
pPoint :: Parser G.Point
pPoint = do
_ <- string "["
optional pWhiteSpace
f1 <- pFloat
pWhiteSpace
f2 <- pFloat
optional pWhiteSpace
_ <- string "]"
optional pWhiteSpace
return (f1, f2)
pPath :: Parser G.Path
pPath = pList pPoint
pLine :: Parser G.Picture
pLine = do
_ <- string "Line"
optional pWhiteSpace
path <- pPath
return $ G.Line path
pLineLoop :: Parser G.Picture
pLineLoop = do
_ <- string "LineLoop"
pWhiteSpace
path <- pPath
return $ G.lineLoop path
pPolygon :: Parser G.Picture
pPolygon = do
_ <- string "Polygon"
pWhiteSpace
path <- pPath
return $ G.Polygon path
pText :: Parser G.Picture
pText = do
s <- pStringLiteral
return $ G.Text s
pImage :: Parser G.Picture
pImage = do
_ <- string "Image"
pWhiteSpace
filePath <- pStringLiteral
let bmp = UIO.unsafePerformIO $ BitmapStore.load filePath
case bmp of
Just x -> return x
Nothing -> fail ("Invalid image file path " ++ filePath)
pImageSection :: Parser G.Picture
pImageSection = do
_ <- string "ImageSection"
pWhiteSpace
x <- L.decimal
pWhiteSpace
y <- L.decimal
pWhiteSpace
width <- L.decimal
pWhiteSpace
height <- L.decimal
pWhiteSpace
(G.Bitmap bitmapData) <- pImage
return $ G.BitmapSection (G.Rectangle (x, y) (width, height)) bitmapData
pImageClear :: Parser G.Picture
pImageClear = do
_ <- string "ImageClear"
pWhiteSpace
filePath <- pStringLiteral
return $ UIO.unsafePerformIO $ BitmapStore.clear filePath
pRotate :: Parser G.Picture
pRotate = do
_ <- string "Rotate"
pWhiteSpace
degrees <- pFloat
pWhiteSpace
p <- pPicture
return $ G.Rotate degrees p
pScale :: Parser G.Picture
pScale = do
_ <- string "Scale"
pWhiteSpace
f1 <- pFloat
pWhiteSpace
f2 <- pFloat
pWhiteSpace
p <- pPicture
return $ G.Scale f1 f2 p
pTranslate :: Parser G.Picture
pTranslate = do
_ <- string "Translate"
pWhiteSpace
f1 <- pFloat
pWhiteSpace
f2 <- pFloat
pWhiteSpace
p <- pPicture
return $ G.Translate f1 f2 p
pPictures :: Parser G.Picture
pPictures = do
optional $ string "Pictures"
optional pWhiteSpace
ps <- pList pPicture
return $ G.Pictures ps
pColor :: Parser G.Picture
pColor = do
_ <- string "Color"
pWhiteSpace
(r, g, b, a) <- pRGBA
pWhiteSpace
p <- pPicture
return $ G.Color (G.makeColorI r g b a) p
pPicture :: Parser G.Picture
pPicture = do
optional pWhiteSpace
p <- choice
[ pBlank
, pPolygon
, pLineLoop
, pLine
, pCircleSolid
, pCircle
, pImageSection
, pImageClear
, pImage
, pThickCircle
, pArcSolid
, pArc
, pThickArc
, pText
, pPictures
, pColor
, pRectangleSolid
, pRectangleUpperSolid
, pRectangleUpperWire
, pRectangleWire
, pSectorWire
, pRotate
, pScale
, pTranslate
]
optional pWhiteSpace
return p
parse :: Text -> Either (ParseErrorBundle Text Void) G.Picture
parse = runParser pPicture "source"