blob: c74f47a049f3495047d143cfe7741df5bb56a64e [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
reed9fbc3f32014-10-21 07:12:58 -070099 local scale = 1.25
reedd2e7dfb2014-10-13 19:43:17 -0700100 for i = 1, #slide do
101 local node = slide[i]
reed9fbc3f32014-10-21 07:12:58 -0700102 local paint = template[node.indent + 1].paint
103 local extra_dy = template[node.indent + 1].extra_dy
reedd2e7dfb2014-10-13 19:43:17 -0700104 local fm = paint:getFontMetrics()
reedbdc49ae2014-10-14 09:34:52 -0700105 local x_offset = -fm.ascent * node.indent
106
reedd2e7dfb2014-10-13 19:43:17 -0700107 y = y - fm.ascent * scale
reedbdc49ae2014-10-14 09:34:52 -0700108 canvas:drawText(node.text, x + x_offset, y, paint)
reed9fbc3f32014-10-21 07:12:58 -0700109 y = y + fm.descent * scale + extra_dy
110 end
111end
112
113function scale_text_delta(template, delta)
114 template = template.slide
115 for i = 1, #template do
116 local paint = template[i].paint
117 paint:setTextSize(paint:getTextSize() + delta)
reed18ea7772014-10-11 11:28:07 -0700118 end
119end
120
reedf355df52014-10-12 12:18:40 -0700121function slide_transition(prev, next, is_forward)
122 local rec = {
123 proc = function(self, canvas, drawSlideProc)
124 if self:isDone() then
125 drawSlideProc(canvas)
126 return nil
127 end
reed96affcd2014-10-13 12:38:04 -0700128 self.prevDrawable:draw(canvas, self.curr_x, 0)
129 self.nextDrawable:draw(canvas, self.curr_x + 640, 0)
reedf355df52014-10-12 12:18:40 -0700130 self.curr_x = self.curr_x + self.step_x
131 return self
132 end
133 }
134 if is_forward then
reed96affcd2014-10-13 12:38:04 -0700135 rec.prevDrawable = prev
136 rec.nextDrawable = next
reedf355df52014-10-12 12:18:40 -0700137 rec.curr_x = 0
138 rec.step_x = -15
139 rec.isDone = function (self) return self.curr_x <= -640 end
140 else
reed96affcd2014-10-13 12:38:04 -0700141 rec.prevDrawable = next
142 rec.nextDrawable = prev
reedf355df52014-10-12 12:18:40 -0700143 rec.curr_x = -640
144 rec.step_x = 15
145 rec.isDone = function (self) return self.curr_x >= 0 end
146 end
147 return rec
148end
149
reed468b1812014-10-19 11:42:54 -0700150function sqr(value) return value * value end
151
reed468b1812014-10-19 11:42:54 -0700152function set_blur(paint, alpha)
153 local sigma = sqr(1 - alpha) * 20
reed9fbc3f32014-10-21 07:12:58 -0700154 paint:setImageFilter(Sk.newBlurImageFilter(sigma, sigma))
reed468b1812014-10-19 11:42:54 -0700155 paint:setAlpha(alpha)
156end
157
reed0d76b952014-10-12 19:05:52 -0700158function fade_slide_transition(prev, next, is_forward)
159 local rec = {
reed468b1812014-10-19 11:42:54 -0700160 paint = Sk.newPaint(),
reed96affcd2014-10-13 12:38:04 -0700161 prevDrawable = prev,
162 nextDrawable = next,
reed0d76b952014-10-12 19:05:52 -0700163 proc = function(self, canvas, drawSlideProc)
164 if self:isDone() then
165 drawSlideProc(canvas)
166 return nil
167 end
reed468b1812014-10-19 11:42:54 -0700168
169 set_blur(self.paint, self.prev_a)
170 self.prevDrawable:draw(canvas, self.prev_x, 0, self.paint)
171
172 set_blur(self.paint, self.next_a)
173 self.nextDrawable:draw(canvas, self.next_x, 0, self.paint)
reed0d76b952014-10-12 19:05:52 -0700174 self:step()
175 return self
176 end
177 }
178 if is_forward then
179 rec.prev_x = 0
180 rec.prev_a = 1
181 rec.next_x = 640
182 rec.next_a = 0
183 rec.isDone = function (self) return self.next_x <= 0 end
184 rec.step = function (self)
185 self.next_x = self.next_x - 20
186 self.next_a = (640 - self.next_x) / 640
187 self.prev_a = 1 - self.next_a
188 end
189 else
190 rec.prev_x = 0
191 rec.prev_a = 1
192 rec.next_x = 0
193 rec.next_a = 0
194 rec.isDone = function (self) return self.prev_x >= 640 end
195 rec.step = function (self)
196 self.prev_x = self.prev_x + 20
197 self.prev_a = (640 - self.prev_x) / 640
198 self.next_a = 1 - self.prev_a
199 end
200 end
201 return rec
202end
203
reed18ea7772014-10-11 11:28:07 -0700204--------------------------------------------------------------------------------------
reed9fbc3f32014-10-21 07:12:58 -0700205function make_tmpl(paint, extra_dy)
206 return { paint = paint, extra_dy = extra_dy }
207end
reed18ea7772014-10-11 11:28:07 -0700208
reedbdc49ae2014-10-14 09:34:52 -0700209function SkiaPoint_make_template()
210 local title = {
211 margin_x = 30,
212 margin_y = 100,
213 }
reed9fbc3f32014-10-21 07:12:58 -0700214 title[1] = make_paint("Arial", 1, 50, { a=1, r=1, g=1, b=1 })
reedbdc49ae2014-10-14 09:34:52 -0700215 title[1]:setTextAlign("center")
reed9fbc3f32014-10-21 07:12:58 -0700216 title[2] = make_paint("Arial", 1, 25, { a=1, r=.75, g=.75, b=.75 })
reedbdc49ae2014-10-14 09:34:52 -0700217 title[2]:setTextAlign("center")
reed18ea7772014-10-11 11:28:07 -0700218
reedbdc49ae2014-10-14 09:34:52 -0700219 local slide = {
220 margin_x = 20,
reed9fbc3f32014-10-21 07:12:58 -0700221 margin_y = 25,
reedbdc49ae2014-10-14 09:34:52 -0700222 }
reed9fbc3f32014-10-21 07:12:58 -0700223 slide[1] = make_tmpl(make_paint("Arial", 1, 36, { a=1, r=1, g=1, b=1 }), 18)
224 slide[2] = make_tmpl(make_paint("Arial", 0, 30, { a=1, r=1, g=1, b=1 }), 0)
225 slide[3] = make_tmpl(make_paint("Arial", 0, 24, { a=1, r=.8, g=.8, b=.8 }), 0)
reedbdc49ae2014-10-14 09:34:52 -0700226
227 return {
228 title = title,
229 slide = slide,
230 }
231end
232
233gTemplate = SkiaPoint_make_template()
reed18ea7772014-10-11 11:28:07 -0700234
235gRedPaint = Sk.newPaint()
236gRedPaint:setAntiAlias(true)
237gRedPaint:setColor{a=1, r=1, g=0, b=0 }
238
reed09a1d672014-10-11 13:13:11 -0700239-- animation.proc is passed the canvas before drawing.
240-- The animation.proc returns itself or another animation (which means keep animating)
241-- or it returns nil, which stops the animation.
242--
243local gCurrAnimation
244
reedf355df52014-10-12 12:18:40 -0700245gSlideIndex = 1
246
247function next_slide()
248 local prev = gSlides[gSlideIndex]
249
250 gSlideIndex = gSlideIndex + 1
251 if gSlideIndex > #gSlides then
252 gSlideIndex = 1
253 end
254
255 spawn_transition(prev, gSlides[gSlideIndex], true)
256end
257
258function prev_slide()
259 local prev = gSlides[gSlideIndex]
260
261 gSlideIndex = gSlideIndex - 1
262 if gSlideIndex < 1 then
263 gSlideIndex = #gSlides
264 end
265
266 spawn_transition(prev, gSlides[gSlideIndex], false)
267end
268
reed96affcd2014-10-13 12:38:04 -0700269function new_drawable_picture(pic)
270 return {
271 picture = pic,
272 width = pic:width(),
273 height = pic:height(),
274 draw = function (self, canvas, x, y, paint)
275 canvas:drawPicture(self.picture, x, y, paint)
276 end
277 }
278end
279
280function new_drawable_image(img)
281 return {
282 image = img,
283 width = img:width(),
284 height = img:height(),
285 draw = function (self, canvas, x, y, paint)
286 canvas:drawImage(self.image, x, y, paint)
287 end
288 }
289end
reedf355df52014-10-12 12:18:40 -0700290
reed468b1812014-10-19 11:42:54 -0700291function convert_to_picture_drawable(slide)
292 local rec = Sk.newPictureRecorder()
293 drawSlide(rec:beginRecording(640, 480), slide, gTemplate)
294 return new_drawable_picture(rec:endRecording())
295end
296
297function convert_to_image_drawable(slide)
298 local surf = Sk.newRasterSurface(640, 480)
299 drawSlide(surf:getCanvas(), slide, gTemplate)
300 return new_drawable_image(surf:newImageSnapshot())
301end
302
303gMakeDrawable = convert_to_picture_drawable
304
reedf355df52014-10-12 12:18:40 -0700305function spawn_transition(prevSlide, nextSlide, is_forward)
306 local transition
307 if is_forward then
308 transition = prevSlide.transition
309 else
310 transition = nextSlide.transition
311 end
312
313 if not transition then
reedd2e7dfb2014-10-13 19:43:17 -0700314 transition = fade_slide_transition
reedf355df52014-10-12 12:18:40 -0700315 end
316
reed468b1812014-10-19 11:42:54 -0700317 local prevDrawable = gMakeDrawable(prevSlide)
318 local nextDrawable = gMakeDrawable(nextSlide)
reed96affcd2014-10-13 12:38:04 -0700319 gCurrAnimation = transition(prevDrawable, nextDrawable, is_forward)
reedf355df52014-10-12 12:18:40 -0700320end
321
322--------------------------------------------------------------------------------------
323
reed09a1d672014-10-11 13:13:11 -0700324function spawn_rotate_animation()
325 gCurrAnimation = {
326 angle = 0,
327 angle_delta = 5,
328 pivot_x = 320,
329 pivot_y = 240,
reedf355df52014-10-12 12:18:40 -0700330 proc = function (self, canvas, drawSlideProc)
331 if self.angle >= 360 then
332 drawSlideProc(canvas)
reed09a1d672014-10-11 13:13:11 -0700333 return nil
334 end
reedf355df52014-10-12 12:18:40 -0700335 canvas:translate(self.pivot_x, self.pivot_y)
336 canvas:rotate(self.angle)
337 canvas:translate(-self.pivot_x, -self.pivot_y)
338 drawSlideProc(canvas)
reed09a1d672014-10-11 13:13:11 -0700339
reedf355df52014-10-12 12:18:40 -0700340 self.angle = self.angle + self.angle_delta
341 return self
reed09a1d672014-10-11 13:13:11 -0700342 end
343 }
344end
345
346function spawn_scale_animation()
347 gCurrAnimation = {
348 scale = 1,
349 scale_delta = .95,
350 scale_limit = 0.2,
351 pivot_x = 320,
352 pivot_y = 240,
reedf355df52014-10-12 12:18:40 -0700353 proc = function (self, canvas, drawSlideProc)
354 if self.scale < self.scale_limit then
355 self.scale = self.scale_limit
356 self.scale_delta = 1 / self.scale_delta
reed09a1d672014-10-11 13:13:11 -0700357 end
reedf355df52014-10-12 12:18:40 -0700358 if self.scale > 1 then
359 drawSlideProc(canvas)
reed09a1d672014-10-11 13:13:11 -0700360 return nil
361 end
reedf355df52014-10-12 12:18:40 -0700362 canvas:translate(self.pivot_x, self.pivot_y)
363 canvas:scale(self.scale, self.scale)
364 canvas:translate(-self.pivot_x, -self.pivot_y)
365 drawSlideProc(canvas)
reed09a1d672014-10-11 13:13:11 -0700366
reedf355df52014-10-12 12:18:40 -0700367 self.scale = self.scale * self.scale_delta
368 return self
reed09a1d672014-10-11 13:13:11 -0700369 end
370 }
371end
372
reed9fbc3f32014-10-21 07:12:58 -0700373local bgPaint = nil
374
375function draw_bg(canvas)
376 if not bgPaint then
377 bgPaint = Sk.newPaint()
378 local grad = Sk.newLinearGradient( 0, 0, { a=1, r=0, g=0, b=.3 },
379 640, 480, { a=1, r=0, g=0, b=.8 })
380 bgPaint:setShader(grad)
381 end
382
383 canvas:drawPaint(bgPaint)
384end
385
reedbdc49ae2014-10-14 09:34:52 -0700386function onDrawContent(canvas, width, height)
387 local matrix = Sk.newMatrix()
388 matrix:setRectToRect(make_rect(0, 0, 640, 480), make_rect(0, 0, width, height), "center")
389 canvas:concat(matrix)
390
reed9fbc3f32014-10-21 07:12:58 -0700391 draw_bg(canvas)
392
reedf355df52014-10-12 12:18:40 -0700393 local drawSlideProc = function(canvas)
reedbdc49ae2014-10-14 09:34:52 -0700394 drawSlide(canvas, gSlides[gSlideIndex], gTemplate)
reed09a1d672014-10-11 13:13:11 -0700395 end
396
reed09a1d672014-10-11 13:13:11 -0700397 if gCurrAnimation then
reedf355df52014-10-12 12:18:40 -0700398 gCurrAnimation = gCurrAnimation:proc(canvas, drawSlideProc)
reed09a1d672014-10-11 13:13:11 -0700399 return true
400 else
reedf355df52014-10-12 12:18:40 -0700401 drawSlideProc(canvas)
reed09a1d672014-10-11 13:13:11 -0700402 return false
403 end
404end
405
406function onClickHandler(x, y)
407 return false
408end
409
410local keyProcs = {
411 n = next_slide,
412 p = prev_slide,
413 r = spawn_rotate_animation,
414 s = spawn_scale_animation,
reed9fbc3f32014-10-21 07:12:58 -0700415 u = function () scale_text_delta(gTemplate, 1) end,
416 d = function () scale_text_delta(gTemplate, -1) end,
reed09a1d672014-10-11 13:13:11 -0700417}
418
419function onCharHandler(uni)
420 local proc = keyProcs[uni]
421 if proc then
422 proc()
423 return true
424 end
425 return false
426end