1gShowBounds = false 2gUseBlurInTransitions = false 3 4gPath = "/skia/trunk/resources/" 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("/skia/trunk/resources/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, stylebits, size, color) 22 local paint = Sk.newPaint(); 23 paint:setAntiAlias(true) 24 paint:setSubpixelText(true) 25 paint:setTypeface(Sk.newTypeface(typefacename, stylebits)) 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 local title = { 106 margin_x = 30, 107 margin_y = 100, 108 } 109 title[1] = make_paint("Arial", 1, 45, { a=1, r=1, g=1, b=1 }) 110 title[1]:setTextAlign("center") 111 title[2] = make_paint("Arial", 1, 25, { a=1, r=.75, g=.75, b=.75 }) 112 title[2]:setTextAlign("center") 113 114 local slide = { 115 margin_x = 20, 116 margin_y = 25, 117 } 118 slide[1] = make_tmpl(make_paint("Arial", 1, 35, { a=1, r=1, g=1, b=1 }), 18) 119 slide[2] = make_tmpl(make_paint("Arial", 0, 25, { a=1, r=1, g=1, b=1 }), 10) 120 slide[3] = make_tmpl(make_paint("Arial", 0, 20, { a=1, r=.9, g=.9, b=.9 }), 5) 121 122 return { 123 title = title, 124 slide = slide, 125 codePaint = make_paint("Courier", 0, 20, { a=1, r=.9, g=.9, b=.9 }), 126 } 127end 128 129gTemplate = SkiaPoint_make_template() 130 131gRedPaint = Sk.newPaint() 132gRedPaint:setAntiAlias(true) 133gRedPaint:setColor{a=1, r=1, g=0, b=0 } 134 135-- animation.proc is passed the canvas before drawing. 136-- The animation.proc returns itself or another animation (which means keep animating) 137-- or it returns nil, which stops the animation. 138-- 139local gCurrAnimation 140 141gSlideIndex = 1 142 143----------------------------------------------------------------------------- 144 145function new_drawable_picture(pic) 146 return { 147 picture = pic, 148 width = pic:width(), 149 height = pic:height(), 150 draw = function (self, canvas, x, y, paint) 151 canvas:drawPicture(self.picture, x, y, paint) 152 end 153 } 154end 155 156function new_drawable_image(img) 157 return { 158 image = img, 159 width = img:width(), 160 height = img:height(), 161 draw = function (self, canvas, x, y, paint) 162 canvas:drawImage(self.image, x, y, paint) 163 end 164 } 165end 166 167function convert_to_picture_drawable(slide) 168 local rec = Sk.newPictureRecorder() 169 drawSlide(rec:beginRecording(640, 480), slide, gTemplate) 170 return new_drawable_picture(rec:endRecording()) 171end 172 173function convert_to_image_drawable(slide) 174 local surf = Sk.newRasterSurface(640, 480) 175 drawSlide(surf:getCanvas(), slide, gTemplate) 176 return new_drawable_image(surf:newImageSnapshot()) 177end 178 179function new_drawable_slide(slide) 180 return { 181 slide = slide, 182 draw = function (self, canvas, x, y, paint) 183 if (nil == paint or ("number" == type(paint) and (1 == paint))) then 184 canvas:save() 185 else 186 canvas:saveLayer(paint) 187 end 188 canvas:translate(x, y) 189 drawSlide(canvas, self.slide, gTemplate) 190 canvas:restore() 191 end 192 } 193end 194 195gNewDrawableFactory = { 196 default = new_drawable_slide, 197 picture = convert_to_picture_drawable, 198 image = convert_to_image_drawable, 199} 200 201----------------------------------------------------------------------------- 202 203function next_slide() 204 local prev = gSlides[gSlideIndex] 205 206 if gSlideIndex < #gSlides then 207 gSlideIndex = gSlideIndex + 1 208 spawn_transition(prev, gSlides[gSlideIndex], true) 209 end 210end 211 212function prev_slide() 213 local prev = gSlides[gSlideIndex] 214 215 if gSlideIndex > 1 then 216 gSlideIndex = gSlideIndex - 1 217 spawn_transition(prev, gSlides[gSlideIndex], false) 218 end 219end 220 221gDrawableType = "default" 222 223load_file("slides_transitions") 224 225function spawn_transition(prevSlide, nextSlide, is_forward) 226 local transition 227 if is_forward then 228 transition = gTransitionTable[nextSlide.transition] 229 else 230 transition = gTransitionTable[prevSlide.transition] 231 end 232 233 if not transition then 234 transition = fade_slide_transition 235 end 236 237 local prevDrawable = gNewDrawableFactory[gDrawableType](prevSlide) 238 local nextDrawable = gNewDrawableFactory[gDrawableType](nextSlide) 239 gCurrAnimation = transition(prevDrawable, nextDrawable, is_forward) 240end 241 242-------------------------------------------------------------------------------------- 243 244function spawn_rotate_animation() 245 gCurrAnimation = { 246 angle = 0, 247 angle_delta = 5, 248 pivot_x = 320, 249 pivot_y = 240, 250 proc = function (self, canvas, drawSlideProc) 251 if self.angle >= 360 then 252 drawSlideProc(canvas) 253 return nil 254 end 255 canvas:translate(self.pivot_x, self.pivot_y) 256 canvas:rotate(self.angle) 257 canvas:translate(-self.pivot_x, -self.pivot_y) 258 drawSlideProc(canvas) 259 260 self.angle = self.angle + self.angle_delta 261 return self 262 end 263 } 264end 265 266function spawn_scale_animation() 267 gCurrAnimation = { 268 scale = 1, 269 scale_delta = .95, 270 scale_limit = 0.2, 271 pivot_x = 320, 272 pivot_y = 240, 273 proc = function (self, canvas, drawSlideProc) 274 if self.scale < self.scale_limit then 275 self.scale = self.scale_limit 276 self.scale_delta = 1 / self.scale_delta 277 end 278 if self.scale > 1 then 279 drawSlideProc(canvas) 280 return nil 281 end 282 canvas:translate(self.pivot_x, self.pivot_y) 283 canvas:scale(self.scale, self.scale) 284 canvas:translate(-self.pivot_x, -self.pivot_y) 285 drawSlideProc(canvas) 286 287 self.scale = self.scale * self.scale_delta 288 return self 289 end 290 } 291end 292 293local bgPaint = nil 294 295function draw_bg(canvas) 296 if not bgPaint then 297 bgPaint = Sk.newPaint() 298 local grad = Sk.newLinearGradient( 0, 0, { a=1, r=0, g=0, b=.3 }, 299 640, 480, { a=1, r=0, g=0, b=.8 }) 300 bgPaint:setShader(grad) 301 bgPaint:setDither(true) 302 end 303 304 canvas:drawPaint(bgPaint) 305end 306 307function onDrawContent(canvas, width, height) 308 local matrix = Sk.newMatrix() 309 matrix:setRectToRect(make_rect(0, 0, 640, 480), make_rect(0, 0, width, height), "center") 310 canvas:concat(matrix) 311 312 draw_bg(canvas) 313 314 local drawSlideProc = function(canvas) 315 drawSlide(canvas, gSlides[gSlideIndex], gTemplate) 316 end 317 318 if gCurrAnimation then 319 gCurrAnimation = gCurrAnimation:proc(canvas, drawSlideProc) 320 return true 321 else 322 drawSlideProc(canvas) 323 return false 324 end 325end 326 327function onClickHandler(x, y) 328 return false 329end 330 331local keyProcs = { 332 n = next_slide, 333 p = prev_slide, 334 r = spawn_rotate_animation, 335 s = spawn_scale_animation, 336 ["="] = function () scale_text_delta(gTemplate, 1) end, 337 ["-"] = function () scale_text_delta(gTemplate, -1) end, 338 339 b = function () gShowBounds = not gShowBounds end, 340 B = function () gUseBlurInTransitions = not gUseBlurInTransitions end, 341 342 ["1"] = function () gDrawableType = "default" end, 343 ["2"] = function () gDrawableType = "picture" end, 344 ["3"] = function () gDrawableType = "image" end, 345} 346 347function onCharHandler(uni) 348 local proc = keyProcs[uni] 349 if proc then 350 proc() 351 return true 352 end 353 return false 354end 355