ListViewAnimation.cpp revision 54fa17f667c285a5c9225e238c8132dfe830ef36
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "TestSceneBase.h" 18#include "utils/Color.h" 19 20#include <cstdio> 21 22class ListViewAnimation; 23 24static Benchmark _ListView(BenchmarkInfo{ 25 "listview", 26 "A mock ListView of scrolling content. Doesn't re-bind/re-record views as they are recycled, so" 27 "won't upload much content (either glyphs, or bitmaps).", 28 simpleCreateScene<ListViewAnimation> 29}); 30 31class ListViewAnimation : public TestScene { 32public: 33 int cardHeight; 34 int cardSpacing; 35 int cardWidth; 36 int cardLeft; 37 sp<RenderNode> listView; 38 std::vector< sp<RenderNode> > cards; 39 void createContent(int width, int height, TestCanvas& canvas) override { 40 srand(0); 41 cardHeight = dp(60); 42 cardSpacing = dp(16); 43 cardWidth = std::min((height - cardSpacing * 2), (int)dp(300)); 44 cardLeft = (width - cardWidth) / 2; 45 46 for (int y = 0; y < height + (cardHeight + cardSpacing - 1); y += (cardHeight + cardSpacing)) { 47 cards.push_back(createCard(cards.size(), y)); 48 } 49 listView = TestUtils::createNode(0, 0, width, height, 50 [this](RenderProperties& props, TestCanvas& canvas) { 51 for (size_t ci = 0; ci < cards.size(); ci++) { 52 canvas.drawRenderNode(cards[ci].get()); 53 } 54 }); 55 56 canvas.drawColor(Color::Grey_500, SkXfermode::kSrcOver_Mode); 57 canvas.drawRenderNode(listView.get()); 58 } 59 60 void doFrame(int frameNr) override { 61 int scrollPx = dp(frameNr) * 3; 62 int cardIndexOffset = scrollPx / (cardSpacing + cardHeight); 63 int pxOffset = -(scrollPx % (cardSpacing + cardHeight)); 64 65 TestCanvas canvas(cardWidth, cardHeight); 66 for (size_t ci = 0; ci < cards.size(); ci++) { 67 // update card position 68 auto card = cards[(ci + cardIndexOffset) % cards.size()]; 69 int top = ((int)ci) * (cardSpacing + cardHeight) + pxOffset; 70 card->mutateStagingProperties().setLeftTopRightBottom( 71 cardLeft, top, cardLeft + cardWidth, top + cardHeight); 72 card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y); 73 74 // draw it to parent DisplayList 75 canvas.drawRenderNode(cards[ci].get()); 76 } 77 listView->setStagingDisplayList(canvas.finishRecording()); 78 } 79private: 80 SkBitmap createRandomCharIcon() { 81 int size = cardHeight - (dp(10) * 2); 82 SkBitmap bitmap = TestUtils::createSkBitmap(size, size); 83 SkCanvas canvas(bitmap); 84 canvas.clear(0); 85 86 SkPaint paint; 87 paint.setAntiAlias(true); 88 SkColor randomColor = BrightColors[rand() % BrightColorsCount]; 89 paint.setColor(randomColor); 90 canvas.drawCircle(size / 2, size / 2, size / 2, paint); 91 92 bool bgDark = SkColorGetR(randomColor) + SkColorGetG(randomColor) + SkColorGetB(randomColor) 93 < 128 * 3; 94 paint.setColor(bgDark ? Color::White : Color::Grey_700); 95 paint.setTextAlign(SkPaint::kCenter_Align); 96 paint.setTextSize(size / 2); 97 char charToShow = 'A' + (rand() % 26); 98 canvas.drawText(&charToShow, 1, size / 2, /*approximate centering*/ size * 0.7, paint); 99 return bitmap; 100 } 101 102 static SkBitmap createBoxBitmap(bool filled) { 103 int size = dp(20); 104 int stroke = dp(2); 105 SkBitmap bitmap = TestUtils::createSkBitmap(size, size); 106 SkCanvas canvas(bitmap); 107 canvas.clear(Color::Transparent); 108 109 SkPaint paint; 110 paint.setAntiAlias(true); 111 paint.setColor(filled ? Color::Yellow_500 : Color::Grey_700); 112 paint.setStyle(filled ? SkPaint::kStrokeAndFill_Style : SkPaint::kStroke_Style); 113 paint.setStrokeWidth(stroke); 114 canvas.drawRect(SkRect::MakeLTRB(stroke, stroke, size - stroke, size - stroke), paint); 115 return bitmap; 116 } 117 118 sp<RenderNode> createCard(int cardId, int top) { 119 return TestUtils::createNode(cardLeft, top, cardLeft + cardWidth, top + cardHeight, 120 [this, cardId](RenderProperties& props, TestCanvas& canvas) { 121 static SkBitmap filledBox = createBoxBitmap(true); 122 static SkBitmap strokedBox = createBoxBitmap(false); 123 124 props.mutableOutline().setRoundRect(0, 0, cardWidth, cardHeight, dp(6), 1); 125 props.mutableOutline().setShouldClip(true); 126 canvas.drawColor(Color::White, SkXfermode::kSrcOver_Mode); 127 128 SkPaint textPaint; 129 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 130 textPaint.setColor(rand() % 2 ? Color::Black : Color::Grey_500); 131 textPaint.setTextSize(dp(20)); 132 textPaint.setAntiAlias(true); 133 char buf[256]; 134 snprintf(buf, sizeof(buf), "This card is #%d", cardId); 135 TestUtils::drawTextToCanvas(&canvas, buf, textPaint, cardHeight, dp(25)); 136 textPaint.setTextSize(dp(15)); 137 TestUtils::drawTextToCanvas(&canvas, "This is some more text on the card", textPaint, 138 cardHeight, dp(45)); 139 140 canvas.drawBitmap(createRandomCharIcon(), dp(10), dp(10), nullptr); 141 142 const SkBitmap& boxBitmap = rand() % 2 ? filledBox : strokedBox; 143 canvas.drawBitmap(boxBitmap, cardWidth - dp(10) - boxBitmap.width(), dp(10), nullptr); 144 }); 145 } 146}; 147