blob: 8035dc45f23cf62d1f5d911ff70ca3b8f1e40e9f [file] [log] [blame]
Chris Craik54fa17f2015-11-25 14:14:53 -08001/*
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
Chris Craik27e58b42015-12-07 10:01:38 -080024static TestScene::Registrar _ListView(TestScene::Info{
Chris Craik54fa17f2015-11-25 14:14:53 -080025 "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).",
Chris Craik27e58b42015-12-07 10:01:38 -080028 TestScene::simpleCreateScene<ListViewAnimation>
Chris Craik54fa17f2015-11-25 14:14:53 -080029});
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
Chris Craik15c3f192015-12-03 12:16:56 -080065 TestCanvas canvas(
66 listView->stagingProperties().getWidth(),
67 listView->stagingProperties().getHeight());
Chris Craik54fa17f2015-11-25 14:14:53 -080068 for (size_t ci = 0; ci < cards.size(); ci++) {
69 // update card position
70 auto card = cards[(ci + cardIndexOffset) % cards.size()];
71 int top = ((int)ci) * (cardSpacing + cardHeight) + pxOffset;
72 card->mutateStagingProperties().setLeftTopRightBottom(
73 cardLeft, top, cardLeft + cardWidth, top + cardHeight);
74 card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
75
76 // draw it to parent DisplayList
77 canvas.drawRenderNode(cards[ci].get());
78 }
John Reck51f2d602016-04-06 07:50:47 -070079 listView->setStagingDisplayList(canvas.finishRecording(), nullptr);
Chris Craik54fa17f2015-11-25 14:14:53 -080080 }
81private:
82 SkBitmap createRandomCharIcon() {
83 int size = cardHeight - (dp(10) * 2);
84 SkBitmap bitmap = TestUtils::createSkBitmap(size, size);
85 SkCanvas canvas(bitmap);
86 canvas.clear(0);
87
88 SkPaint paint;
89 paint.setAntiAlias(true);
90 SkColor randomColor = BrightColors[rand() % BrightColorsCount];
91 paint.setColor(randomColor);
92 canvas.drawCircle(size / 2, size / 2, size / 2, paint);
93
94 bool bgDark = SkColorGetR(randomColor) + SkColorGetG(randomColor) + SkColorGetB(randomColor)
95 < 128 * 3;
96 paint.setColor(bgDark ? Color::White : Color::Grey_700);
97 paint.setTextAlign(SkPaint::kCenter_Align);
98 paint.setTextSize(size / 2);
99 char charToShow = 'A' + (rand() % 26);
100 canvas.drawText(&charToShow, 1, size / 2, /*approximate centering*/ size * 0.7, paint);
101 return bitmap;
102 }
103
104 static SkBitmap createBoxBitmap(bool filled) {
105 int size = dp(20);
106 int stroke = dp(2);
107 SkBitmap bitmap = TestUtils::createSkBitmap(size, size);
108 SkCanvas canvas(bitmap);
109 canvas.clear(Color::Transparent);
110
111 SkPaint paint;
112 paint.setAntiAlias(true);
113 paint.setColor(filled ? Color::Yellow_500 : Color::Grey_700);
114 paint.setStyle(filled ? SkPaint::kStrokeAndFill_Style : SkPaint::kStroke_Style);
115 paint.setStrokeWidth(stroke);
116 canvas.drawRect(SkRect::MakeLTRB(stroke, stroke, size - stroke, size - stroke), paint);
117 return bitmap;
118 }
119
120 sp<RenderNode> createCard(int cardId, int top) {
121 return TestUtils::createNode(cardLeft, top, cardLeft + cardWidth, top + cardHeight,
122 [this, cardId](RenderProperties& props, TestCanvas& canvas) {
123 static SkBitmap filledBox = createBoxBitmap(true);
124 static SkBitmap strokedBox = createBoxBitmap(false);
125
Chris Craik15c3f192015-12-03 12:16:56 -0800126 // TODO: switch to using round rect clipping, once merging correctly handles that
127 SkPaint roundRectPaint;
128 roundRectPaint.setAntiAlias(true);
129 roundRectPaint.setColor(Color::White);
130 canvas.drawRoundRect(0, 0, cardWidth, cardHeight, dp(6), dp(6), roundRectPaint);
Chris Craik54fa17f2015-11-25 14:14:53 -0800131
132 SkPaint textPaint;
133 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
134 textPaint.setColor(rand() % 2 ? Color::Black : Color::Grey_500);
135 textPaint.setTextSize(dp(20));
136 textPaint.setAntiAlias(true);
137 char buf[256];
138 snprintf(buf, sizeof(buf), "This card is #%d", cardId);
sergeyvdccca442016-03-21 15:38:21 -0700139 TestUtils::drawUtf8ToCanvas(&canvas, buf, textPaint, cardHeight, dp(25));
Chris Craik54fa17f2015-11-25 14:14:53 -0800140 textPaint.setTextSize(dp(15));
sergeyvdccca442016-03-21 15:38:21 -0700141 TestUtils::drawUtf8ToCanvas(&canvas, "This is some more text on the card", textPaint,
Chris Craik54fa17f2015-11-25 14:14:53 -0800142 cardHeight, dp(45));
143
144 canvas.drawBitmap(createRandomCharIcon(), dp(10), dp(10), nullptr);
145
146 const SkBitmap& boxBitmap = rand() % 2 ? filledBox : strokedBox;
147 canvas.drawBitmap(boxBitmap, cardWidth - dp(10) - boxBitmap.width(), dp(10), nullptr);
148 });
149 }
150};