blob: b2c9b902c311b6ef3198980428bbbf452b417907 [file] [log] [blame]
reedd2e7dfb2014-10-13 19:43:17 -07001function tostr(t)
2 local str = ""
3 for k, v in next, t do
4 if #str > 0 then
5 str = str .. ", "
6 end
7 if type(k) == "number" then
8 str = str .. "[" .. k .. "] = "
9 else
10 str = str .. tostring(k) .. " = "
11 end
12 if type(v) == "table" then
13 str = str .. "{ " .. tostr(v) .. " }"
14 elseif type(v) == "string" then
15 str = str .. '"' .. v .. '"'
16 else
17 str = str .. tostring(v)
18 end
19 end
20 return str
21end
22
23
24function trim_ws(s)
25 return s:match("^%s*(.*)")
26end
27
28function count_hypens(s)
29 local leftover = s:match("^-*(.*)")
30 return string.len(s) - string.len(leftover)
31end
32
33function parse_file(file)
34 local slides = {}
35 local block = {}
36
37 for line in file:lines() do
38 local s = trim_ws(line)
39 if #s == 0 then -- done with a block
40 if #block > 0 then
41 slides[#slides + 1] = block
42 block = {}
43 end
44 else
45 local n = count_hypens(s)
46 block[#block + 1] = {
47 indent = n,
48 text = trim_ws(s:sub(n + 1, -1))
49 }
50 end
51 end
52 return slides
53end
54
55function pretty_print_slide(slide)
56 io.write("{\n")
57 for i = 1, #slide do
58 local node = slide[i]
59 for j = 0, node.indent do
60 io.write(" ")
61 end
62 io.write("{ ")
63 io.write(tostr(node))
64 io.write(" },\n")
65 end
66 io.write("},\n")
67end
68
69function pretty_print_slides(slides)
70 io.write("gSlides = {\n")
71 for i = 1, #slides do
72 pretty_print_slide(slides[i])
73 end
74 io.write("}\n")
75end
76
77gSlides = parse_file(io.open("/skia/trunk/resources/slides_content.lua", "r"))
reed18ea7772014-10-11 11:28:07 -070078
reedbdc49ae2014-10-14 09:34:52 -070079function make_rect(l, t, r, b)
80 return { left = l, top = t, right = r, bottom = b }
81end
82
83function make_paint(typefacename, stylebits, size, color)
reed18ea7772014-10-11 11:28:07 -070084 local paint = Sk.newPaint();
85 paint:setAntiAlias(true)
reed09a1d672014-10-11 13:13:11 -070086 paint:setSubpixelText(true)
reedbdc49ae2014-10-14 09:34:52 -070087 paint:setTypeface(Sk.newTypeface(typefacename, stylebits))
reed18ea7772014-10-11 11:28:07 -070088 paint:setTextSize(size)
89 paint:setColor(color)
90 return paint
91end
92
reedbdc49ae2014-10-14 09:34:52 -070093function drawSlide(canvas, slide, template)
94 template = template.slide -- need to sniff the slide to know if we're title or slide
95
96 local x = template.margin_x
97 local y = template.margin_y
98
reedd2e7dfb2014-10-13 19:43:17 -070099 local scale = 1.15
reedd2e7dfb2014-10-13 19:43:17 -0700100 for i = 1, #slide do
101 local node = slide[i]
reedbdc49ae2014-10-14 09:34:52 -0700102 local paint = template[node.indent + 1]
reedd2e7dfb2014-10-13 19:43:17 -0700103 local fm = paint:getFontMetrics()
reedbdc49ae2014-10-14 09:34:52 -0700104 local x_offset = -fm.ascent * node.indent
105
reedd2e7dfb2014-10-13 19:43:17 -0700106 y = y - fm.ascent * scale
reedbdc49ae2014-10-14 09:34:52 -0700107 canvas:drawText(node.text, x + x_offset, y, paint)
reedd2e7dfb2014-10-13 19:43:17 -0700108 y = y + fm.descent * scale
reed18ea7772014-10-11 11:28:07 -0700109 end
110end
111
reedf355df52014-10-12 12:18:40 -0700112function slide_transition(prev, next, is_forward)
113 local rec = {
114 proc = function(self, canvas, drawSlideProc)
115 if self:isDone() then
116 drawSlideProc(canvas)
117 return nil
118 end
reed96affcd2014-10-13 12:38:04 -0700119 self.prevDrawable:draw(canvas, self.curr_x, 0)
120 self.nextDrawable:draw(canvas, self.curr_x + 640, 0)
reedf355df52014-10-12 12:18:40 -0700121 self.curr_x = self.curr_x + self.step_x
122 return self
123 end
124 }
125 if is_forward then
reed96affcd2014-10-13 12:38:04 -0700126 rec.prevDrawable = prev
127 rec.nextDrawable = next
reedf355df52014-10-12 12:18:40 -0700128 rec.curr_x = 0
129 rec.step_x = -15
130 rec.isDone = function (self) return self.curr_x <= -640 end
131 else
reed96affcd2014-10-13 12:38:04 -0700132 rec.prevDrawable = next
133 rec.nextDrawable = prev
reedf355df52014-10-12 12:18:40 -0700134 rec.curr_x = -640
135 rec.step_x = 15
136 rec.isDone = function (self) return self.curr_x >= 0 end
137 end
138 return rec
139end
140
reed468b1812014-10-19 11:42:54 -0700141function sqr(value) return value * value end
142
143function ease(value)
144function set_blur(paint, alpha)
145 local sigma = sqr(1 - alpha) * 20
146-- paint:setImageFilter(Sk.newBlurImageFilter(sigma, sigma))
147 paint:setAlpha(alpha)
148end
149
reed0d76b952014-10-12 19:05:52 -0700150function fade_slide_transition(prev, next, is_forward)
151 local rec = {
reed468b1812014-10-19 11:42:54 -0700152 paint = Sk.newPaint(),
reed96affcd2014-10-13 12:38:04 -0700153 prevDrawable = prev,
154 nextDrawable = next,
reed0d76b952014-10-12 19:05:52 -0700155 proc = function(self, canvas, drawSlideProc)
156 if self:isDone() then
157 drawSlideProc(canvas)
158 return nil
159 end
reed468b1812014-10-19 11:42:54 -0700160
161 set_blur(self.paint, self.prev_a)
162 self.prevDrawable:draw(canvas, self.prev_x, 0, self.paint)
163
164 set_blur(self.paint, self.next_a)
165 self.nextDrawable:draw(canvas, self.next_x, 0, self.paint)
reed0d76b952014-10-12 19:05:52 -0700166 self:step()
167 return self
168 end
169 }
170 if is_forward then
171 rec.prev_x = 0
172 rec.prev_a = 1
173 rec.next_x = 640
174 rec.next_a = 0
175 rec.isDone = function (self) return self.next_x <= 0 end
176 rec.step = function (self)
177 self.next_x = self.next_x - 20
178 self.next_a = (640 - self.next_x) / 640
179 self.prev_a = 1 - self.next_a
180 end
181 else
182 rec.prev_x = 0
183 rec.prev_a = 1
184 rec.next_x = 0
185 rec.next_a = 0
186 rec.isDone = function (self) return self.prev_x >= 640 end
187 rec.step = function (self)
188 self.prev_x = self.prev_x + 20
189 self.prev_a = (640 - self.prev_x) / 640
190 self.next_a = 1 - self.prev_a
191 end
192 end
193 return rec
194end
195
reed18ea7772014-10-11 11:28:07 -0700196--------------------------------------------------------------------------------------
197
reedbdc49ae2014-10-14 09:34:52 -0700198function SkiaPoint_make_template()
199 local title = {
200 margin_x = 30,
201 margin_y = 100,
202 }
203 title[1] = make_paint("Arial", 1, 50, { a=1, r=0, g=0, b=0 })
204 title[1]:setTextAlign("center")
205 title[2] = make_paint("Arial", 1, 25, { a=1, r=.3, g=.3, b=.3 })
206 title[2]:setTextAlign("center")
reed18ea7772014-10-11 11:28:07 -0700207
reedbdc49ae2014-10-14 09:34:52 -0700208 local slide = {
209 margin_x = 20,
210 margin_y = 30,
211 }
212 slide[1] = make_paint("Arial", 1, 36, { a=1, r=0, g=0, b=0 })
213 slide[2] = make_paint("Arial", 0, 30, { a=1, r=0, g=0, b=0 })
214 slide[3] = make_paint("Arial", 0, 24, { a=1, r=.2, g=.2, b=.2 })
215
216 return {
217 title = title,
218 slide = slide,
219 }
220end
221
222gTemplate = SkiaPoint_make_template()
reed18ea7772014-10-11 11:28:07 -0700223
224gRedPaint = Sk.newPaint()
225gRedPaint:setAntiAlias(true)
226gRedPaint:setColor{a=1, r=1, g=0, b=0 }
227
reed09a1d672014-10-11 13:13:11 -0700228-- animation.proc is passed the canvas before drawing.
229-- The animation.proc returns itself or another animation (which means keep animating)
230-- or it returns nil, which stops the animation.
231--
232local gCurrAnimation
233
reedf355df52014-10-12 12:18:40 -0700234gSlideIndex = 1
235
236function next_slide()
237 local prev = gSlides[gSlideIndex]
238
239 gSlideIndex = gSlideIndex + 1
240 if gSlideIndex > #gSlides then
241 gSlideIndex = 1
242 end
243
244 spawn_transition(prev, gSlides[gSlideIndex], true)
245end
246
247function prev_slide()
248 local prev = gSlides[gSlideIndex]
249
250 gSlideIndex = gSlideIndex - 1
251 if gSlideIndex < 1 then
252 gSlideIndex = #gSlides
253 end
254
255 spawn_transition(prev, gSlides[gSlideIndex], false)
256end
257
reed96affcd2014-10-13 12:38:04 -0700258function new_drawable_picture(pic)
259 return {
260 picture = pic,
261 width = pic:width(),
262 height = pic:height(),
263 draw = function (self, canvas, x, y, paint)
264 canvas:drawPicture(self.picture, x, y, paint)
265 end
266 }
267end
268
269function new_drawable_image(img)
270 return {
271 image = img,
272 width = img:width(),
273 height = img:height(),
274 draw = function (self, canvas, x, y, paint)
275 canvas:drawImage(self.image, x, y, paint)
276 end
277 }
278end
reedf355df52014-10-12 12:18:40 -0700279
reed468b1812014-10-19 11:42:54 -0700280function convert_to_picture_drawable(slide)
281 local rec = Sk.newPictureRecorder()
282 drawSlide(rec:beginRecording(640, 480), slide, gTemplate)
283 return new_drawable_picture(rec:endRecording())
284end
285
286function convert_to_image_drawable(slide)
287 local surf = Sk.newRasterSurface(640, 480)
288 drawSlide(surf:getCanvas(), slide, gTemplate)
289 return new_drawable_image(surf:newImageSnapshot())
290end
291
292gMakeDrawable = convert_to_picture_drawable
293
reedf355df52014-10-12 12:18:40 -0700294function spawn_transition(prevSlide, nextSlide, is_forward)
295 local transition
296 if is_forward then
297 transition = prevSlide.transition
298 else
299 transition = nextSlide.transition
300 end
301
302 if not transition then
reedd2e7dfb2014-10-13 19:43:17 -0700303 transition = fade_slide_transition
reedf355df52014-10-12 12:18:40 -0700304 end
305
reed468b1812014-10-19 11:42:54 -0700306 local prevDrawable = gMakeDrawable(prevSlide)
307 local nextDrawable = gMakeDrawable(nextSlide)
reed96affcd2014-10-13 12:38:04 -0700308 gCurrAnimation = transition(prevDrawable, nextDrawable, is_forward)
reedf355df52014-10-12 12:18:40 -0700309end
310
311--------------------------------------------------------------------------------------
312
reed09a1d672014-10-11 13:13:11 -0700313function spawn_rotate_animation()
314 gCurrAnimation = {
315 angle = 0,
316 angle_delta = 5,
317 pivot_x = 320,
318 pivot_y = 240,
reedf355df52014-10-12 12:18:40 -0700319 proc = function (self, canvas, drawSlideProc)
320 if self.angle >= 360 then
321 drawSlideProc(canvas)
reed09a1d672014-10-11 13:13:11 -0700322 return nil
323 end
reedf355df52014-10-12 12:18:40 -0700324 canvas:translate(self.pivot_x, self.pivot_y)
325 canvas:rotate(self.angle)
326 canvas:translate(-self.pivot_x, -self.pivot_y)
327 drawSlideProc(canvas)
reed09a1d672014-10-11 13:13:11 -0700328
reedf355df52014-10-12 12:18:40 -0700329 self.angle = self.angle + self.angle_delta
330 return self
reed09a1d672014-10-11 13:13:11 -0700331 end
332 }
333end
334
335function spawn_scale_animation()
336 gCurrAnimation = {
337 scale = 1,
338 scale_delta = .95,
339 scale_limit = 0.2,
340 pivot_x = 320,
341 pivot_y = 240,
reedf355df52014-10-12 12:18:40 -0700342 proc = function (self, canvas, drawSlideProc)
343 if self.scale < self.scale_limit then
344 self.scale = self.scale_limit
345 self.scale_delta = 1 / self.scale_delta
reed09a1d672014-10-11 13:13:11 -0700346 end
reedf355df52014-10-12 12:18:40 -0700347 if self.scale > 1 then
348 drawSlideProc(canvas)
reed09a1d672014-10-11 13:13:11 -0700349 return nil
350 end
reedf355df52014-10-12 12:18:40 -0700351 canvas:translate(self.pivot_x, self.pivot_y)
352 canvas:scale(self.scale, self.scale)
353 canvas:translate(-self.pivot_x, -self.pivot_y)
354 drawSlideProc(canvas)
reed09a1d672014-10-11 13:13:11 -0700355
reedf355df52014-10-12 12:18:40 -0700356 self.scale = self.scale * self.scale_delta
357 return self
reed09a1d672014-10-11 13:13:11 -0700358 end
359 }
360end
361
reedbdc49ae2014-10-14 09:34:52 -0700362function onDrawContent(canvas, width, height)
363 local matrix = Sk.newMatrix()
364 matrix:setRectToRect(make_rect(0, 0, 640, 480), make_rect(0, 0, width, height), "center")
365 canvas:concat(matrix)
366
reedf355df52014-10-12 12:18:40 -0700367 local drawSlideProc = function(canvas)
reedbdc49ae2014-10-14 09:34:52 -0700368 drawSlide(canvas, gSlides[gSlideIndex], gTemplate)
reed09a1d672014-10-11 13:13:11 -0700369 end
370
reed09a1d672014-10-11 13:13:11 -0700371 if gCurrAnimation then
reedf355df52014-10-12 12:18:40 -0700372 gCurrAnimation = gCurrAnimation:proc(canvas, drawSlideProc)
reed09a1d672014-10-11 13:13:11 -0700373 return true
374 else
reedf355df52014-10-12 12:18:40 -0700375 drawSlideProc(canvas)
reed09a1d672014-10-11 13:13:11 -0700376 return false
377 end
378end
379
380function onClickHandler(x, y)
381 return false
382end
383
384local keyProcs = {
385 n = next_slide,
386 p = prev_slide,
387 r = spawn_rotate_animation,
388 s = spawn_scale_animation,
389}
390
391function onCharHandler(uni)
392 local proc = keyProcs[uni]
393 if proc then
394 proc()
395 return true
396 end
397 return false
398end