aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/PictureRenderer.cpp
blob: 5f3496c60f39f19c0d011e469b50f38a887c7d51 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "PictureRenderer.h"
#include "SamplePipeControllers.h"
#include "SkCanvas.h"
#include "SkDevice.h"
#include "SkGPipe.h"
#include "SkPicture.h"
#include "SkTDArray.h"
#include "SkTypes.h"
#include "picture_utils.h"

namespace sk_tools {

enum {
    kDefaultTileWidth = 256,
    kDefaultTileHeight = 256
};

void PipePictureRenderer::render(SkPicture* pict, SkCanvas* canvas) {
    PipeController pipeController(canvas);
    SkGPipeWriter writer;
    SkCanvas* pipeCanvas = writer.startRecording(&pipeController);
    pipeCanvas->drawPicture(*pict);
    writer.endRecording();
}

void SimplePictureRenderer::render(SkPicture* pict, SkCanvas* canvas) {
    canvas->drawPicture(*pict);
}

TiledPictureRenderer::TiledPictureRenderer()
    : fTileWidth(kDefaultTileWidth)
    , fTileHeight(kDefaultTileHeight) {}

void TiledPictureRenderer::init(const SkPicture& pict) {
    deleteTiles();

    if (fTileWidthPercentage > 0) {
        fTileWidth = sk_float_ceil2int(fTileWidthPercentage * pict.width() / 100);
    }
    if (fTileHeightPercentage > 0) {
        fTileHeight = sk_float_ceil2int(fTileHeightPercentage * pict.height() / 100);
    }

    setupTiles(pict);
}

void TiledPictureRenderer::render(SkPicture* pict, SkCanvas* canvas) {
    for (int i = 0; i < fTiles.count(); ++i) {
        fTiles[i].fCanvas->drawPicture(*pict);
    }

    copyTilesToCanvas(*pict, canvas);
}

TiledPictureRenderer::~TiledPictureRenderer() {
    deleteTiles();
}

void TiledPictureRenderer::clipTile(const SkPicture& picture, const TileInfo& tile) {
    SkRect clip = SkRect::MakeWH(SkIntToScalar(picture.width()),
                                 SkIntToScalar(picture.height()));
    tile.fCanvas->clipRect(clip);
}

void TiledPictureRenderer::addTile(const SkPicture& picture, int tile_x_start, int tile_y_start) {
    TileInfo* tile = fTiles.push();

    tile->fBitmap = SkNEW(SkBitmap);
    sk_tools::setup_bitmap(tile->fBitmap, fTileWidth, fTileHeight);

    tile->fCanvas = SkNEW_ARGS(SkCanvas, (*(tile->fBitmap)));
    tile->fCanvas->translate(SkIntToScalar(-tile_x_start), SkIntToScalar(-tile_y_start));
    clipTile(picture, *tile);
}

void TiledPictureRenderer::setupTiles(const SkPicture& picture) {
    for (int tile_y_start = 0; tile_y_start < picture.height();
         tile_y_start += fTileHeight) {
        for (int tile_x_start = 0; tile_x_start < picture.width();
             tile_x_start += fTileWidth) {
            addTile(picture, tile_x_start, tile_y_start);
        }
    }
}

void TiledPictureRenderer::deleteTiles() {
    for (int i = 0; i < fTiles.count(); ++i) {
        SkDELETE(fTiles[i].fCanvas);
        SkDELETE(fTiles[i].fBitmap);
    }

    fTiles.reset();
}

void TiledPictureRenderer::copyTilesToCanvas(const SkPicture& pict, SkCanvas* destination) {
    int tile_index = 0;
    for (int tile_y_start = 0; tile_y_start < pict.height();
         tile_y_start += fTileHeight) {
        for (int tile_x_start = 0; tile_x_start < pict.width();
             tile_x_start += fTileWidth) {
            SkASSERT(tile_index < fTiles.count());
            SkBitmap source = fTiles[tile_index].fCanvas->getDevice()->accessBitmap(false);
            destination->drawBitmap(source, 
                                    SkIntToScalar(tile_x_start), 
                                    SkIntToScalar(tile_y_start));
            ++tile_index;
        }
    }
}

}