16997ebbe5cf06c938cc893e1d0217dc4048edf82reed@google.com/*
26997ebbe5cf06c938cc893e1d0217dc4048edf82reed@google.com * Copyright 2012 Google Inc.
36997ebbe5cf06c938cc893e1d0217dc4048edf82reed@google.com *
46997ebbe5cf06c938cc893e1d0217dc4048edf82reed@google.com * Use of this source code is governed by a BSD-style license that can be
56997ebbe5cf06c938cc893e1d0217dc4048edf82reed@google.com * found in the LICENSE file.
66997ebbe5cf06c938cc893e1d0217dc4048edf82reed@google.com */
76997ebbe5cf06c938cc893e1d0217dc4048edf82reed@google.com
8f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.com#include "SkBitmap.h"
970e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org#include "SkCanvas.h"
107def5e1630d47cdbfa4b58a9c86bc060693c4d79scroggo@google.com#include "SkImagePriv.h"
117def5e1630d47cdbfa4b58a9c86bc060693c4d79scroggo@google.com#include "SkImage_Base.h"
12f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.com
137def5e1630d47cdbfa4b58a9c86bc060693c4d79scroggo@google.comstatic SkImage_Base* as_IB(SkImage* image) {
14f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.com    return static_cast<SkImage_Base*>(image);
15f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.com}
16f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.com
177def5e1630d47cdbfa4b58a9c86bc060693c4d79scroggo@google.comstatic const SkImage_Base* as_IB(const SkImage* image) {
187def5e1630d47cdbfa4b58a9c86bc060693c4d79scroggo@google.com    return static_cast<const SkImage_Base*>(image);
197def5e1630d47cdbfa4b58a9c86bc060693c4d79scroggo@google.com}
207def5e1630d47cdbfa4b58a9c86bc060693c4d79scroggo@google.com
21f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.comuint32_t SkImage::NextUniqueID() {
22f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.com    static int32_t gUniqueID;
23f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.com
24f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.com    // never return 0;
25f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.com    uint32_t id;
26f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.com    do {
27f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.com        id = sk_atomic_inc(&gUniqueID) + 1;
28f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.com    } while (0 == id);
29f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.com    return id;
30f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.com}
31f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.com
32f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.comvoid SkImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
33f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.com                   const SkPaint* paint) {
347def5e1630d47cdbfa4b58a9c86bc060693c4d79scroggo@google.com    as_IB(this)->onDraw(canvas, x, y, paint);
35f6627b78f933b77b358ac0791c520f99b0e79fcareed@google.com}
36da90474b5fcc019fb0971d12360bd05213ad4dc8junov@chromium.org
37dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.orgvoid SkImage::draw(SkCanvas* canvas, const SkRect* src, const SkRect& dst,
38dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org                   const SkPaint* paint) {
39dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org    as_IB(this)->onDrawRectToRect(canvas, src, dst, paint);
40dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org}
41dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org
424f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.comconst void* SkImage::peekPixels(SkImageInfo* info, size_t* rowBytes) const {
434f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    SkImageInfo infoStorage;
444f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    size_t rowBytesStorage;
454f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    if (NULL == info) {
464f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        info = &infoStorage;
474f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    }
484f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    if (NULL == rowBytes) {
494f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        rowBytes = &rowBytesStorage;
504f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    }
514f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    return as_IB(this)->onPeekPixels(info, rowBytes);
524f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com}
534f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com
544f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.combool SkImage::readPixels(SkBitmap* bitmap, const SkIRect* subset) const {
554f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    if (NULL == bitmap) {
564f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        return false;
574f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    }
585e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org
594f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    SkIRect bounds = SkIRect::MakeWH(this->width(), this->height());
604f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com
614f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    // trim against the bitmap, if its already been allocated
624f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    if (bitmap->pixelRef()) {
634f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        bounds.fRight = SkMin32(bounds.fRight, bitmap->width());
644f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        bounds.fBottom = SkMin32(bounds.fBottom, bitmap->height());
654f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        if (bounds.isEmpty()) {
664f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com            return false;
674f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        }
684f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    }
694f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com
704f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    if (subset && !bounds.intersect(*subset)) {
714f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        // perhaps we could return true + empty-bitmap?
724f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        return false;
734f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    }
744f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    return as_IB(this)->onReadPixels(bitmap, bounds);
754f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com}
764f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com
77da90474b5fcc019fb0971d12360bd05213ad4dc8junov@chromium.orgGrTexture* SkImage::getTexture() {
787def5e1630d47cdbfa4b58a9c86bc060693c4d79scroggo@google.com    return as_IB(this)->onGetTexture();
797def5e1630d47cdbfa4b58a9c86bc060693c4d79scroggo@google.com}
807def5e1630d47cdbfa4b58a9c86bc060693c4d79scroggo@google.com
817def5e1630d47cdbfa4b58a9c86bc060693c4d79scroggo@google.comSkData* SkImage::encode(SkImageEncoder::Type type, int quality) const {
827def5e1630d47cdbfa4b58a9c86bc060693c4d79scroggo@google.com    SkBitmap bm;
837def5e1630d47cdbfa4b58a9c86bc060693c4d79scroggo@google.com    if (as_IB(this)->getROPixels(&bm)) {
847def5e1630d47cdbfa4b58a9c86bc060693c4d79scroggo@google.com        return SkImageEncoder::EncodeData(bm, type, quality);
857def5e1630d47cdbfa4b58a9c86bc060693c4d79scroggo@google.com    }
867def5e1630d47cdbfa4b58a9c86bc060693c4d79scroggo@google.com    return NULL;
87da90474b5fcc019fb0971d12360bd05213ad4dc8junov@chromium.org}
884f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com
894f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com///////////////////////////////////////////////////////////////////////////////
904f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com
914f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.comstatic bool raster_canvas_supports(const SkImageInfo& info) {
924f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    switch (info.fColorType) {
9328fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
944f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com            return kUnpremul_SkAlphaType != info.fAlphaType;
954f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        case kRGB_565_SkColorType:
964f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com            return true;
974f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        case kAlpha_8_SkColorType:
984f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com            return true;
994f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        default:
1004f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com            break;
1014f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    }
1024f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    return false;
1034f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com}
1044f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com
1054f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.combool SkImage_Base::onReadPixels(SkBitmap* bitmap, const SkIRect& subset) const {
1064f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    if (bitmap->pixelRef()) {
107466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org        const SkImageInfo info = bitmap->info();
108466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org        if (kUnknown_SkColorType == info.colorType()) {
1094f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com            return false;
1104f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        }
1114f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        if (!raster_canvas_supports(info)) {
1124f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com            return false;
1134f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        }
1144f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    } else {
115466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org        const SkImageInfo info = SkImageInfo::MakeN32Premul(subset.width(), subset.height());
1164f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        SkBitmap tmp;
1174f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        if (!tmp.allocPixels(info)) {
1184f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com            return false;
1194f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        }
1204f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        *bitmap = tmp;
1214f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    }
1224f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com
1234f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    SkRect srcR, dstR;
1244f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    srcR.set(subset);
1254f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    dstR = srcR;
1264f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    dstR.offset(-dstR.left(), -dstR.top());
1275e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org
1284f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    SkCanvas canvas(*bitmap);
1294f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com
1304f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    SkPaint paint;
1314f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    paint.setXfermodeMode(SkXfermode::kClear_Mode);
1324f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    canvas.drawRect(dstR, paint);
1334f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com
1344f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    const_cast<SkImage_Base*>(this)->onDrawRectToRect(&canvas, &srcR, dstR, NULL);
1354f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    return true;
1364f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com}
137