• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1gShowBounds = false
2gUseBlurInTransitions = false
3
4gPath = "resources/lua/"
5
6function load_file(file)
7    local prev_path = package.path
8    package.path = package.path .. ";" .. gPath .. file .. ".lua"
9    require(file)
10    package.path = prev_path
11end
12
13load_file("slides_utils")
14
15gSlides = parse_file(io.open("resources/lua/slides_content2.lua", "r"))
16
17function make_rect(l, t, r, b)
18    return { left = l, top = t, right = r, bottom = b }
19end
20
21function make_paint(typefacename, style, size, color)
22    local paint = Sk.newPaint();
23    paint:setAntiAlias(true)
24    paint:setSubpixelText(true)
25    paint:setTypeface(Sk.newTypeface(typefacename, style))
26    paint:setTextSize(size)
27    paint:setColor(color)
28    return paint
29end
30
31function 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
42function 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
49function drawSlide(canvas, slide, master_template)
50
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
58
59    local x = template.margin_x
60    local y = template.margin_y
61    local scale = 1.25
62
63    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]
70            y = y - fm.ascent * scale
71            canvas:drawText(node.text, x, y, paint)
72            y = y + fm.descent * scale
73        end
74        return
75    end
76
77    for i = 1, #slide do
78        local node = slide[i]
79        local paint = template[node.indent + 1].paint
80        local extra_dy = template[node.indent + 1].extra_dy
81        local fm = paint:getFontMetrics()
82        local x_offset = -fm.ascent * node.indent * 1.25
83
84        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)
88        y = newBottom + paint:getTextSize() * .5 + extra_dy
89
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
96    end
97end
98
99--------------------------------------------------------------------------------------
100function make_tmpl(paint, extra_dy)
101    return { paint = paint, extra_dy = extra_dy }
102end
103
104function SkiaPoint_make_template()
105    normal = Sk.newFontStyle()
106    bold = Sk.newFontStyle(700)
107    local title = {
108        margin_x = 30,
109        margin_y = 100,
110    }
111    title[1] = make_paint("Arial", bold, 45, { a=1, r=1, g=1, b=1 })
112    title[1]:setTextAlign("center")
113    title[2] = make_paint("Arial", bold, 25, { a=1, r=.75, g=.75, b=.75 })
114    title[2]:setTextAlign("center")
115
116    local slide = {
117        margin_x = 20,
118        margin_y = 25,
119    }
120    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)
123
124    return {
125        title = title,
126        slide = slide,
127        codePaint = make_paint("Courier", normal, 20, { a=1, r=.9, g=.9, b=.9 }),
128    }
129end
130
131gTemplate = SkiaPoint_make_template()
132
133gRedPaint = Sk.newPaint()
134gRedPaint:setAntiAlias(true)
135gRedPaint:setColor{a=1, r=1, g=0, b=0 }
136
137-- 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
143gSlideIndex = 1
144
145-----------------------------------------------------------------------------
146
147function 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
168
169function 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
181function 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
197gNewDrawableFactory = {
198    default = new_drawable_slide,
199    picture = convert_to_picture_drawable,
200    image = convert_to_image_drawable,
201}
202
203-----------------------------------------------------------------------------
204
205function next_slide()
206    local prev = gSlides[gSlideIndex]
207
208    if gSlideIndex < #gSlides then
209        gSlideIndex = gSlideIndex + 1
210        spawn_transition(prev, gSlides[gSlideIndex], true)
211    end
212end
213
214function prev_slide()
215    local prev = gSlides[gSlideIndex]
216
217    if gSlideIndex > 1 then
218        gSlideIndex = gSlideIndex - 1
219        spawn_transition(prev, gSlides[gSlideIndex], false)
220    end
221end
222
223gDrawableType = "default"
224
225load_file("slides_transitions")
226
227function spawn_transition(prevSlide, nextSlide, is_forward)
228    local transition
229    if is_forward then
230        transition = gTransitionTable[nextSlide.transition]
231    else
232        transition = gTransitionTable[prevSlide.transition]
233    end
234
235    if not transition then
236        transition = fade_slide_transition
237    end
238
239    local prevDrawable = gNewDrawableFactory[gDrawableType](prevSlide)
240    local nextDrawable = gNewDrawableFactory[gDrawableType](nextSlide)
241    gCurrAnimation = transition(prevDrawable, nextDrawable, is_forward)
242end
243
244--------------------------------------------------------------------------------------
245
246function spawn_rotate_animation()
247    gCurrAnimation = {
248        angle = 0,
249        angle_delta = 5,
250        pivot_x = 320,
251        pivot_y = 240,
252        proc = function (self, canvas, drawSlideProc)
253            if self.angle >= 360 then
254                drawSlideProc(canvas)
255                return nil
256            end
257            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)
261
262            self.angle = self.angle + self.angle_delta
263            return self
264        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,
275        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
279            end
280            if self.scale > 1 then
281                drawSlideProc(canvas)
282                return nil
283            end
284            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)
288
289            self.scale = self.scale * self.scale_delta
290            return self
291        end
292    }
293end
294
295local 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)
303        bgPaint:setDither(true)
304    end
305
306    canvas:drawPaint(bgPaint)
307end
308
309function 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
314    draw_bg(canvas)
315
316    local drawSlideProc = function(canvas)
317        drawSlide(canvas, gSlides[gSlideIndex], gTemplate)
318    end
319
320    if gCurrAnimation then
321        gCurrAnimation = gCurrAnimation:proc(canvas, drawSlideProc)
322        return true
323    else
324        drawSlideProc(canvas)
325        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,
338    ["="] = function () scale_text_delta(gTemplate, 1) end,
339    ["-"] = function () scale_text_delta(gTemplate, -1) end,
340
341    b = function () gShowBounds = not gShowBounds end,
342    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,
347}
348
349function onCharHandler(uni)
350    local proc = keyProcs[uni]
351    if proc then
352        proc()
353        return true
354    end
355    return false
356end
357