bb8a0ababa
BUG=skia: TBR= Review URL: https://codereview.chromium.org/698563004
365 lines
9.7 KiB
Lua
365 lines
9.7 KiB
Lua
gShowBounds = false
|
|
|
|
gPath = "/skia/trunk/resources/"
|
|
|
|
function load_file(file)
|
|
local prev_path = package.path
|
|
package.path = package.path .. ";" .. gPath .. file .. ".lua"
|
|
require(file)
|
|
package.path = prev_path
|
|
end
|
|
|
|
load_file("slides_utils")
|
|
|
|
gSlides = parse_file(io.open("/skia/trunk/resources/slides_content2.lua", "r"))
|
|
|
|
function make_rect(l, t, r, b)
|
|
return { left = l, top = t, right = r, bottom = b }
|
|
end
|
|
|
|
function make_paint(typefacename, stylebits, size, color)
|
|
local paint = Sk.newPaint();
|
|
paint:setAntiAlias(true)
|
|
paint:setSubpixelText(true)
|
|
paint:setTypeface(Sk.newTypeface(typefacename, stylebits))
|
|
paint:setTextSize(size)
|
|
paint:setColor(color)
|
|
return paint
|
|
end
|
|
|
|
function center_rect(sw, sh, dst)
|
|
local dw = dst.right - dst.left
|
|
local dh = dst.bottom - dst.top
|
|
|
|
local rw, rh
|
|
|
|
if sw / sh > dw / dh then
|
|
rw = dw
|
|
rh = sh * dw / sw
|
|
else
|
|
rh = dh
|
|
rw = sw * dh / sh
|
|
end
|
|
|
|
local x = dst.left + ((sw - rw) / 2)
|
|
local y = dst.top + ((sh - rh) / 2)
|
|
return make_rect(x, y, x + rw, y + rh)
|
|
end
|
|
|
|
function draw_image_centered(canvas, image)
|
|
local sw = image:width()
|
|
local sh = image:height()
|
|
local dstR = center_rect(image:width(), image:height(), make_rect(20, 20, 620, 460))
|
|
canvas:drawImageRect(image, nil, dstR)
|
|
end
|
|
|
|
function draw_bullet(canvas, x, y, paint, indent)
|
|
if 0 == indent then
|
|
return
|
|
end
|
|
local ps = paint:getTextSize()
|
|
local cx = x - ps * .8
|
|
local cy = y - ps * .4
|
|
local radius = ps * .2
|
|
canvas:drawCircle(cx, cy, radius, paint)
|
|
end
|
|
|
|
function stroke_rect(canvas, rect, color)
|
|
local paint = Sk.newPaint()
|
|
paint:setStroke(true);
|
|
paint:setColor(color)
|
|
canvas:drawRect(rect, paint)
|
|
end
|
|
|
|
function drawSlide(canvas, slide, master_template)
|
|
|
|
if #slide == 1 then
|
|
template = master_template.title
|
|
canvas:drawText(slide[1].text, 320, 240, template[1])
|
|
return
|
|
end
|
|
|
|
template = master_template.slide
|
|
|
|
local x = template.margin_x
|
|
local y = template.margin_y
|
|
local scale = 1.25
|
|
|
|
if slide.blockstyle == "code" then
|
|
local paint = master_template.codePaint
|
|
local fm = paint:getFontMetrics()
|
|
local height = #slide * (fm.descent - fm.ascent)
|
|
y = (480 - height) / 2
|
|
for i = 1, #slide do
|
|
local node = slide[i]
|
|
y = y - fm.ascent * scale
|
|
canvas:drawText(node.text, x, y, paint)
|
|
y = y + fm.descent * scale
|
|
end
|
|
return
|
|
end
|
|
|
|
for i = 1, #slide do
|
|
local node = slide[i]
|
|
local paint = template[node.indent + 1].paint
|
|
local extra_dy = template[node.indent + 1].extra_dy
|
|
local fm = paint:getFontMetrics()
|
|
local x_offset = -fm.ascent * node.indent * 1.25
|
|
|
|
local bounds = make_rect(x + x_offset, y, 620, 640)
|
|
local blob, newBottom = Sk.newTextBlob(node.text, bounds, paint)
|
|
draw_bullet(canvas, x + x_offset, y - fm.ascent, paint, node.indent)
|
|
canvas:drawTextBlob(blob, 0, 0, paint)
|
|
y = newBottom + paint:getTextSize() * .5
|
|
|
|
if gShowBounds then
|
|
bounds.bottom = newBottom
|
|
stroke_rect(canvas, bounds, {a=1,r=0,g=1,b=0})
|
|
stroke_rect(canvas, blob:bounds(), {a=1,r=1,g=0,b=0})
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------------
|
|
function make_tmpl(paint, extra_dy)
|
|
return { paint = paint, extra_dy = extra_dy }
|
|
end
|
|
|
|
function SkiaPoint_make_template()
|
|
local title = {
|
|
margin_x = 30,
|
|
margin_y = 100,
|
|
}
|
|
title[1] = make_paint("Arial", 1, 45, { a=1, r=1, g=1, b=1 })
|
|
title[1]:setTextAlign("center")
|
|
title[2] = make_paint("Arial", 1, 25, { a=1, r=.75, g=.75, b=.75 })
|
|
title[2]:setTextAlign("center")
|
|
|
|
local slide = {
|
|
margin_x = 20,
|
|
margin_y = 25,
|
|
}
|
|
slide[1] = make_tmpl(make_paint("Arial", 1, 35, { a=1, r=1, g=1, b=1 }), 18)
|
|
slide[2] = make_tmpl(make_paint("Arial", 0, 25, { a=1, r=1, g=1, b=1 }), 0)
|
|
slide[3] = make_tmpl(make_paint("Arial", 0, 20, { a=1, r=.9, g=.9, b=.9 }), 0)
|
|
|
|
return {
|
|
title = title,
|
|
slide = slide,
|
|
codePaint = make_paint("Courier", 0, 20, { a=1, r=.9, g=.9, b=.9 }),
|
|
}
|
|
end
|
|
|
|
gTemplate = SkiaPoint_make_template()
|
|
|
|
gRedPaint = Sk.newPaint()
|
|
gRedPaint:setAntiAlias(true)
|
|
gRedPaint:setColor{a=1, r=1, g=0, b=0 }
|
|
|
|
-- animation.proc is passed the canvas before drawing.
|
|
-- The animation.proc returns itself or another animation (which means keep animating)
|
|
-- or it returns nil, which stops the animation.
|
|
--
|
|
local gCurrAnimation
|
|
|
|
gSlideIndex = 1
|
|
|
|
function new_drawable_picture(pic)
|
|
return {
|
|
picture = pic,
|
|
width = pic:width(),
|
|
height = pic:height(),
|
|
draw = function (self, canvas, x, y, paint)
|
|
canvas:drawPicture(self.picture, x, y, paint)
|
|
end
|
|
}
|
|
end
|
|
|
|
function new_drawable_image(img)
|
|
return {
|
|
image = img,
|
|
width = img:width(),
|
|
height = img:height(),
|
|
draw = function (self, canvas, x, y, paint)
|
|
canvas:drawImage(self.image, x, y, paint)
|
|
end
|
|
}
|
|
end
|
|
|
|
function new_drawable_slide(slide)
|
|
return {
|
|
slide = slide,
|
|
draw = function (self, canvas, x, y, paint)
|
|
if (nil == paint or ("number" == type(paint) and (1 == paint))) then
|
|
canvas:save()
|
|
else
|
|
canvas:saveLayer(paint)
|
|
end
|
|
canvas:translate(x, y)
|
|
drawSlide(canvas, self.slide, gTemplate)
|
|
canvas:restore()
|
|
end
|
|
}
|
|
end
|
|
|
|
function next_slide()
|
|
local prev = gSlides[gSlideIndex]
|
|
|
|
if gSlideIndex < #gSlides then
|
|
gSlideIndex = gSlideIndex + 1
|
|
spawn_transition(prev, gSlides[gSlideIndex], true)
|
|
end
|
|
end
|
|
|
|
function prev_slide()
|
|
local prev = gSlides[gSlideIndex]
|
|
|
|
if gSlideIndex > 1 then
|
|
gSlideIndex = gSlideIndex - 1
|
|
spawn_transition(prev, gSlides[gSlideIndex], false)
|
|
end
|
|
end
|
|
|
|
function convert_to_picture_drawable(slide)
|
|
local rec = Sk.newPictureRecorder()
|
|
drawSlide(rec:beginRecording(640, 480), slide, gTemplate)
|
|
return new_drawable_picture(rec:endRecording())
|
|
end
|
|
|
|
function convert_to_image_drawable(slide)
|
|
local surf = Sk.newRasterSurface(640, 480)
|
|
drawSlide(surf:getCanvas(), slide, gTemplate)
|
|
return new_drawable_image(surf:newImageSnapshot())
|
|
end
|
|
|
|
gMakeDrawable = new_drawable_slide
|
|
|
|
load_file("slides_transitions")
|
|
|
|
function spawn_transition(prevSlide, nextSlide, is_forward)
|
|
local transition
|
|
if is_forward then
|
|
transition = gTransitionTable[nextSlide.transition]
|
|
else
|
|
transition = gTransitionTable[prevSlide.transition]
|
|
end
|
|
|
|
if not transition then
|
|
transition = fade_slide_transition
|
|
end
|
|
|
|
local prevDrawable = gMakeDrawable(prevSlide)
|
|
local nextDrawable = gMakeDrawable(nextSlide)
|
|
gCurrAnimation = transition(prevDrawable, nextDrawable, is_forward)
|
|
end
|
|
|
|
--------------------------------------------------------------------------------------
|
|
|
|
function spawn_rotate_animation()
|
|
gCurrAnimation = {
|
|
angle = 0,
|
|
angle_delta = 5,
|
|
pivot_x = 320,
|
|
pivot_y = 240,
|
|
proc = function (self, canvas, drawSlideProc)
|
|
if self.angle >= 360 then
|
|
drawSlideProc(canvas)
|
|
return nil
|
|
end
|
|
canvas:translate(self.pivot_x, self.pivot_y)
|
|
canvas:rotate(self.angle)
|
|
canvas:translate(-self.pivot_x, -self.pivot_y)
|
|
drawSlideProc(canvas)
|
|
|
|
self.angle = self.angle + self.angle_delta
|
|
return self
|
|
end
|
|
}
|
|
end
|
|
|
|
function spawn_scale_animation()
|
|
gCurrAnimation = {
|
|
scale = 1,
|
|
scale_delta = .95,
|
|
scale_limit = 0.2,
|
|
pivot_x = 320,
|
|
pivot_y = 240,
|
|
proc = function (self, canvas, drawSlideProc)
|
|
if self.scale < self.scale_limit then
|
|
self.scale = self.scale_limit
|
|
self.scale_delta = 1 / self.scale_delta
|
|
end
|
|
if self.scale > 1 then
|
|
drawSlideProc(canvas)
|
|
return nil
|
|
end
|
|
canvas:translate(self.pivot_x, self.pivot_y)
|
|
canvas:scale(self.scale, self.scale)
|
|
canvas:translate(-self.pivot_x, -self.pivot_y)
|
|
drawSlideProc(canvas)
|
|
|
|
self.scale = self.scale * self.scale_delta
|
|
return self
|
|
end
|
|
}
|
|
end
|
|
|
|
local bgPaint = nil
|
|
|
|
function draw_bg(canvas)
|
|
if not bgPaint then
|
|
bgPaint = Sk.newPaint()
|
|
local grad = Sk.newLinearGradient( 0, 0, { a=1, r=0, g=0, b=.3 },
|
|
640, 480, { a=1, r=0, g=0, b=.8 })
|
|
bgPaint:setShader(grad)
|
|
bgPaint:setDither(true)
|
|
end
|
|
|
|
canvas:drawPaint(bgPaint)
|
|
end
|
|
|
|
function onDrawContent(canvas, width, height)
|
|
local matrix = Sk.newMatrix()
|
|
matrix:setRectToRect(make_rect(0, 0, 640, 480), make_rect(0, 0, width, height), "center")
|
|
canvas:concat(matrix)
|
|
|
|
draw_bg(canvas)
|
|
|
|
local drawSlideProc = function(canvas)
|
|
drawSlide(canvas, gSlides[gSlideIndex], gTemplate)
|
|
end
|
|
|
|
if gCurrAnimation then
|
|
gCurrAnimation = gCurrAnimation:proc(canvas, drawSlideProc)
|
|
return true
|
|
else
|
|
drawSlideProc(canvas)
|
|
return false
|
|
end
|
|
end
|
|
|
|
function onClickHandler(x, y)
|
|
return false
|
|
end
|
|
|
|
local keyProcs = {
|
|
n = next_slide,
|
|
p = prev_slide,
|
|
r = spawn_rotate_animation,
|
|
s = spawn_scale_animation,
|
|
["="] = function () scale_text_delta(gTemplate, 1) end,
|
|
["-"] = function () scale_text_delta(gTemplate, -1) end,
|
|
|
|
b = function () gShowBounds = not gShowBounds end,
|
|
}
|
|
|
|
function onCharHandler(uni)
|
|
local proc = keyProcs[uni]
|
|
if proc then
|
|
proc()
|
|
return true
|
|
end
|
|
return false
|
|
end
|