blob: eb34dd8138723e82591ef3215a465bdc0eaf929d [file] [log] [blame]
reed1b6ab442014-11-03 19:55:41 -08001gShowBounds = false
reed7b864662014-11-04 13:24:47 -08002gUseBlurInTransitions = false
reed86217d82014-10-25 20:44:40 -07003
Ben Wagnerd6de89b2018-05-22 11:24:21 -04004gPath = "resources/lua/"
reed86217d82014-10-25 20:44:40 -07005
6function load_file(file)
reed07dada72014-10-29 20:36:05 -07007 local prev_path = package.path
reed86217d82014-10-25 20:44:40 -07008 package.path = package.path .. ";" .. gPath .. file .. ".lua"
9 require(file)
reed07dada72014-10-29 20:36:05 -070010 package.path = prev_path
reedd2e7dfb2014-10-13 19:43:17 -070011end
12
reed86217d82014-10-25 20:44:40 -070013load_file("slides_utils")
reedd2e7dfb2014-10-13 19:43:17 -070014
Ben Wagnerd6de89b2018-05-22 11:24:21 -040015gSlides = parse_file(io.open("resources/lua/slides_content2.lua", "r"))
reed18ea7772014-10-11 11:28:07 -070016
reedbdc49ae2014-10-14 09:34:52 -070017function make_rect(l, t, r, b)
18 return { left = l, top = t, right = r, bottom = b }
19end
20
Ben Wagnerc6c10b42017-08-07 09:56:21 -040021function make_paint(typefacename, style, size, color)
reed18ea7772014-10-11 11:28:07 -070022 local paint = Sk.newPaint();
23 paint:setAntiAlias(true)
reed09a1d672014-10-11 13:13:11 -070024 paint:setSubpixelText(true)
Ben Wagnerc6c10b42017-08-07 09:56:21 -040025 paint:setTypeface(Sk.newTypeface(typefacename, style))
reed18ea7772014-10-11 11:28:07 -070026 paint:setTextSize(size)
27 paint:setColor(color)
28 return paint
29end
30
reed9e233b22014-11-03 12:18:24 -080031function draw_bullet(canvas, x, y, paint, indent)
32 if 0 == indent then
33 return
34 end
35 local ps = paint:getTextSize()
36 local cx = x - ps * .8
37 local cy = y - ps * .4
38 local radius = ps * .2
39 canvas:drawCircle(cx, cy, radius, paint)
40end
41
reed1b6ab442014-11-03 19:55:41 -080042function stroke_rect(canvas, rect, color)
43 local paint = Sk.newPaint()
44 paint:setStroke(true);
45 paint:setColor(color)
46 canvas:drawRect(rect, paint)
47end
48
reedde330ff2014-11-02 19:19:34 -080049function drawSlide(canvas, slide, master_template)
reedbb8a0ab2014-11-03 22:32:07 -080050
51 if #slide == 1 then
52 template = master_template.title
53 canvas:drawText(slide[1].text, 320, 240, template[1])
54 return
55 end
56
57 template = master_template.slide
reedbdc49ae2014-10-14 09:34:52 -070058
59 local x = template.margin_x
60 local y = template.margin_y
reed9e233b22014-11-03 12:18:24 -080061 local scale = 1.25
reedbdc49ae2014-10-14 09:34:52 -070062
reedde330ff2014-11-02 19:19:34 -080063 if slide.blockstyle == "code" then
64 local paint = master_template.codePaint
65 local fm = paint:getFontMetrics()
66 local height = #slide * (fm.descent - fm.ascent)
67 y = (480 - height) / 2
68 for i = 1, #slide do
69 local node = slide[i]
reed9e233b22014-11-03 12:18:24 -080070 y = y - fm.ascent * scale
reedde330ff2014-11-02 19:19:34 -080071 canvas:drawText(node.text, x, y, paint)
reed9e233b22014-11-03 12:18:24 -080072 y = y + fm.descent * scale
reedde330ff2014-11-02 19:19:34 -080073 end
74 return
75 end
76
reedd2e7dfb2014-10-13 19:43:17 -070077 for i = 1, #slide do
78 local node = slide[i]
reed9fbc3f32014-10-21 07:12:58 -070079 local paint = template[node.indent + 1].paint
80 local extra_dy = template[node.indent + 1].extra_dy
reedd2e7dfb2014-10-13 19:43:17 -070081 local fm = paint:getFontMetrics()
reed9e233b22014-11-03 12:18:24 -080082 local x_offset = -fm.ascent * node.indent * 1.25
reedbdc49ae2014-10-14 09:34:52 -070083
reed1b6ab442014-11-03 19:55:41 -080084 local bounds = make_rect(x + x_offset, y, 620, 640)
85 local blob, newBottom = Sk.newTextBlob(node.text, bounds, paint)
86 draw_bullet(canvas, x + x_offset, y - fm.ascent, paint, node.indent)
87 canvas:drawTextBlob(blob, 0, 0, paint)
reed36c9c112014-11-04 10:58:42 -080088 y = newBottom + paint:getTextSize() * .5 + extra_dy
reed1b6ab442014-11-03 19:55:41 -080089
90 if gShowBounds then
91 bounds.bottom = newBottom
92 stroke_rect(canvas, bounds, {a=1,r=0,g=1,b=0})
93 stroke_rect(canvas, blob:bounds(), {a=1,r=1,g=0,b=0})
94 end
95
reed9fbc3f32014-10-21 07:12:58 -070096 end
97end
98
reed18ea7772014-10-11 11:28:07 -070099--------------------------------------------------------------------------------------
reed9fbc3f32014-10-21 07:12:58 -0700100function make_tmpl(paint, extra_dy)
101 return { paint = paint, extra_dy = extra_dy }
102end
reed18ea7772014-10-11 11:28:07 -0700103
reedbdc49ae2014-10-14 09:34:52 -0700104function SkiaPoint_make_template()
Ben Wagnerc6c10b42017-08-07 09:56:21 -0400105 normal = Sk.newFontStyle()
106 bold = Sk.newFontStyle(700)
reedbdc49ae2014-10-14 09:34:52 -0700107 local title = {
108 margin_x = 30,
109 margin_y = 100,
110 }
Ben Wagnerc6c10b42017-08-07 09:56:21 -0400111 title[1] = make_paint("Arial", bold, 45, { a=1, r=1, g=1, b=1 })
reedbdc49ae2014-10-14 09:34:52 -0700112 title[1]:setTextAlign("center")
Ben Wagnerc6c10b42017-08-07 09:56:21 -0400113 title[2] = make_paint("Arial", bold, 25, { a=1, r=.75, g=.75, b=.75 })
reedbdc49ae2014-10-14 09:34:52 -0700114 title[2]:setTextAlign("center")
reed18ea7772014-10-11 11:28:07 -0700115
reedbdc49ae2014-10-14 09:34:52 -0700116 local slide = {
117 margin_x = 20,
reed9fbc3f32014-10-21 07:12:58 -0700118 margin_y = 25,
reedbdc49ae2014-10-14 09:34:52 -0700119 }
Ben Wagnerc6c10b42017-08-07 09:56:21 -0400120 slide[1] = make_tmpl(make_paint("Arial", bold, 35, { a=1, r=1, g=1, b=1 }), 18)
121 slide[2] = make_tmpl(make_paint("Arial", normal, 25, { a=1, r=1, g=1, b=1 }), 10)
122 slide[3] = make_tmpl(make_paint("Arial", normal, 20, { a=1, r=.9, g=.9, b=.9 }), 5)
reedbdc49ae2014-10-14 09:34:52 -0700123
124 return {
125 title = title,
126 slide = slide,
Ben Wagnerc6c10b42017-08-07 09:56:21 -0400127 codePaint = make_paint("Courier", normal, 20, { a=1, r=.9, g=.9, b=.9 }),
reedbdc49ae2014-10-14 09:34:52 -0700128 }
129end
130
131gTemplate = SkiaPoint_make_template()
reed18ea7772014-10-11 11:28:07 -0700132
133gRedPaint = Sk.newPaint()
134gRedPaint:setAntiAlias(true)
135gRedPaint:setColor{a=1, r=1, g=0, b=0 }
136
reed09a1d672014-10-11 13:13:11 -0700137-- animation.proc is passed the canvas before drawing.
138-- The animation.proc returns itself or another animation (which means keep animating)
139-- or it returns nil, which stops the animation.
140--
141local gCurrAnimation
142
reedf355df52014-10-12 12:18:40 -0700143gSlideIndex = 1
144
reed7b864662014-11-04 13:24:47 -0800145-----------------------------------------------------------------------------
146
reed96affcd2014-10-13 12:38:04 -0700147function new_drawable_picture(pic)
148 return {
149 picture = pic,
150 width = pic:width(),
151 height = pic:height(),
152 draw = function (self, canvas, x, y, paint)
153 canvas:drawPicture(self.picture, x, y, paint)
154 end
155 }
156end
157
158function new_drawable_image(img)
159 return {
160 image = img,
161 width = img:width(),
162 height = img:height(),
163 draw = function (self, canvas, x, y, paint)
164 canvas:drawImage(self.image, x, y, paint)
165 end
166 }
167end
reedf355df52014-10-12 12:18:40 -0700168
reed7b864662014-11-04 13:24:47 -0800169function convert_to_picture_drawable(slide)
170 local rec = Sk.newPictureRecorder()
171 drawSlide(rec:beginRecording(640, 480), slide, gTemplate)
172 return new_drawable_picture(rec:endRecording())
173end
174
175function convert_to_image_drawable(slide)
176 local surf = Sk.newRasterSurface(640, 480)
177 drawSlide(surf:getCanvas(), slide, gTemplate)
178 return new_drawable_image(surf:newImageSnapshot())
179end
180
reed86217d82014-10-25 20:44:40 -0700181function new_drawable_slide(slide)
182 return {
183 slide = slide,
184 draw = function (self, canvas, x, y, paint)
185 if (nil == paint or ("number" == type(paint) and (1 == paint))) then
186 canvas:save()
187 else
188 canvas:saveLayer(paint)
189 end
190 canvas:translate(x, y)
191 drawSlide(canvas, self.slide, gTemplate)
192 canvas:restore()
193 end
194 }
195end
196
reed7b864662014-11-04 13:24:47 -0800197gNewDrawableFactory = {
198 default = new_drawable_slide,
199 picture = convert_to_picture_drawable,
200 image = convert_to_image_drawable,
201}
202
203-----------------------------------------------------------------------------
204
reed86217d82014-10-25 20:44:40 -0700205function next_slide()
206 local prev = gSlides[gSlideIndex]
207
reedbb8a0ab2014-11-03 22:32:07 -0800208 if gSlideIndex < #gSlides then
209 gSlideIndex = gSlideIndex + 1
210 spawn_transition(prev, gSlides[gSlideIndex], true)
reed86217d82014-10-25 20:44:40 -0700211 end
reed86217d82014-10-25 20:44:40 -0700212end
213
214function prev_slide()
215 local prev = gSlides[gSlideIndex]
216
reedbb8a0ab2014-11-03 22:32:07 -0800217 if gSlideIndex > 1 then
218 gSlideIndex = gSlideIndex - 1
219 spawn_transition(prev, gSlides[gSlideIndex], false)
reed86217d82014-10-25 20:44:40 -0700220 end
reed86217d82014-10-25 20:44:40 -0700221end
222
reed7b864662014-11-04 13:24:47 -0800223gDrawableType = "default"
reed468b1812014-10-19 11:42:54 -0700224
reed07dada72014-10-29 20:36:05 -0700225load_file("slides_transitions")
226
reedf355df52014-10-12 12:18:40 -0700227function spawn_transition(prevSlide, nextSlide, is_forward)
228 local transition
229 if is_forward then
reed07dada72014-10-29 20:36:05 -0700230 transition = gTransitionTable[nextSlide.transition]
reedf355df52014-10-12 12:18:40 -0700231 else
reed07dada72014-10-29 20:36:05 -0700232 transition = gTransitionTable[prevSlide.transition]
reedf355df52014-10-12 12:18:40 -0700233 end
234
235 if not transition then
reedd2e7dfb2014-10-13 19:43:17 -0700236 transition = fade_slide_transition
reedf355df52014-10-12 12:18:40 -0700237 end
238
reed7b864662014-11-04 13:24:47 -0800239 local prevDrawable = gNewDrawableFactory[gDrawableType](prevSlide)
240 local nextDrawable = gNewDrawableFactory[gDrawableType](nextSlide)
reed96affcd2014-10-13 12:38:04 -0700241 gCurrAnimation = transition(prevDrawable, nextDrawable, is_forward)
reedf355df52014-10-12 12:18:40 -0700242end
243
244--------------------------------------------------------------------------------------
245
reed09a1d672014-10-11 13:13:11 -0700246function spawn_rotate_animation()
247 gCurrAnimation = {
248 angle = 0,
249 angle_delta = 5,
250 pivot_x = 320,
251 pivot_y = 240,
reedf355df52014-10-12 12:18:40 -0700252 proc = function (self, canvas, drawSlideProc)
253 if self.angle >= 360 then
254 drawSlideProc(canvas)
reed09a1d672014-10-11 13:13:11 -0700255 return nil
256 end
reedf355df52014-10-12 12:18:40 -0700257 canvas:translate(self.pivot_x, self.pivot_y)
258 canvas:rotate(self.angle)
259 canvas:translate(-self.pivot_x, -self.pivot_y)
260 drawSlideProc(canvas)
reed09a1d672014-10-11 13:13:11 -0700261
reedf355df52014-10-12 12:18:40 -0700262 self.angle = self.angle + self.angle_delta
263 return self
reed09a1d672014-10-11 13:13:11 -0700264 end
265 }
266end
267
268function spawn_scale_animation()
269 gCurrAnimation = {
270 scale = 1,
271 scale_delta = .95,
272 scale_limit = 0.2,
273 pivot_x = 320,
274 pivot_y = 240,
reedf355df52014-10-12 12:18:40 -0700275 proc = function (self, canvas, drawSlideProc)
276 if self.scale < self.scale_limit then
277 self.scale = self.scale_limit
278 self.scale_delta = 1 / self.scale_delta
reed09a1d672014-10-11 13:13:11 -0700279 end
reedf355df52014-10-12 12:18:40 -0700280 if self.scale > 1 then
281 drawSlideProc(canvas)
reed09a1d672014-10-11 13:13:11 -0700282 return nil
283 end
reedf355df52014-10-12 12:18:40 -0700284 canvas:translate(self.pivot_x, self.pivot_y)
285 canvas:scale(self.scale, self.scale)
286 canvas:translate(-self.pivot_x, -self.pivot_y)
287 drawSlideProc(canvas)
reed09a1d672014-10-11 13:13:11 -0700288
reedf355df52014-10-12 12:18:40 -0700289 self.scale = self.scale * self.scale_delta
290 return self
reed09a1d672014-10-11 13:13:11 -0700291 end
292 }
293end
294
reed9fbc3f32014-10-21 07:12:58 -0700295local bgPaint = nil
296
297function draw_bg(canvas)
298 if not bgPaint then
299 bgPaint = Sk.newPaint()
300 local grad = Sk.newLinearGradient( 0, 0, { a=1, r=0, g=0, b=.3 },
301 640, 480, { a=1, r=0, g=0, b=.8 })
302 bgPaint:setShader(grad)
reedbb8a0ab2014-11-03 22:32:07 -0800303 bgPaint:setDither(true)
reed9fbc3f32014-10-21 07:12:58 -0700304 end
305
306 canvas:drawPaint(bgPaint)
307end
308
reedbdc49ae2014-10-14 09:34:52 -0700309function onDrawContent(canvas, width, height)
310 local matrix = Sk.newMatrix()
311 matrix:setRectToRect(make_rect(0, 0, 640, 480), make_rect(0, 0, width, height), "center")
312 canvas:concat(matrix)
313
reed9fbc3f32014-10-21 07:12:58 -0700314 draw_bg(canvas)
315
reedf355df52014-10-12 12:18:40 -0700316 local drawSlideProc = function(canvas)
reedbdc49ae2014-10-14 09:34:52 -0700317 drawSlide(canvas, gSlides[gSlideIndex], gTemplate)
reed09a1d672014-10-11 13:13:11 -0700318 end
319
reed09a1d672014-10-11 13:13:11 -0700320 if gCurrAnimation then
reedf355df52014-10-12 12:18:40 -0700321 gCurrAnimation = gCurrAnimation:proc(canvas, drawSlideProc)
reed09a1d672014-10-11 13:13:11 -0700322 return true
323 else
reedf355df52014-10-12 12:18:40 -0700324 drawSlideProc(canvas)
reed09a1d672014-10-11 13:13:11 -0700325 return false
326 end
327end
328
329function onClickHandler(x, y)
330 return false
331end
332
333local keyProcs = {
334 n = next_slide,
335 p = prev_slide,
336 r = spawn_rotate_animation,
337 s = spawn_scale_animation,
reedc7663982014-10-21 10:46:01 -0700338 ["="] = function () scale_text_delta(gTemplate, 1) end,
339 ["-"] = function () scale_text_delta(gTemplate, -1) end,
reed1b6ab442014-11-03 19:55:41 -0800340
341 b = function () gShowBounds = not gShowBounds end,
reed7b864662014-11-04 13:24:47 -0800342 B = function () gUseBlurInTransitions = not gUseBlurInTransitions end,
343
344 ["1"] = function () gDrawableType = "default" end,
345 ["2"] = function () gDrawableType = "picture" end,
346 ["3"] = function () gDrawableType = "image" end,
reed09a1d672014-10-11 13:13:11 -0700347}
348
349function onCharHandler(uni)
350 local proc = keyProcs[uni]
351 if proc then
352 proc()
353 return true
354 end
355 return false
356end