1/*
2 * Copyright 2010 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkImageInfo.h"
9#include "SkReadBuffer.h"
10#include "SkWriteBuffer.h"
11
12static bool profile_type_is_valid(SkColorProfileType profileType) {
13    return (profileType >= 0) && (profileType <= kLastEnum_SkColorProfileType);
14}
15
16static bool alpha_type_is_valid(SkAlphaType alphaType) {
17    return (alphaType >= 0) && (alphaType <= kLastEnum_SkAlphaType);
18}
19
20static bool color_type_is_valid(SkColorType colorType) {
21    return (colorType >= 0) && (colorType <= kLastEnum_SkColorType);
22}
23
24void SkImageInfo::unflatten(SkReadBuffer& buffer) {
25    fWidth = buffer.read32();
26    fHeight = buffer.read32();
27
28    uint32_t packed = buffer.read32();
29    SkASSERT(0 == (packed >> 24));
30    fProfileType = (SkColorProfileType)((packed >> 16) & 0xFF);
31    fAlphaType = (SkAlphaType)((packed >> 8) & 0xFF);
32    fColorType = (SkColorType)((packed >> 0) & 0xFF);
33    buffer.validate(profile_type_is_valid(fProfileType) &&
34                    alpha_type_is_valid(fAlphaType) &&
35                    color_type_is_valid(fColorType));
36}
37
38void SkImageInfo::flatten(SkWriteBuffer& buffer) const {
39    buffer.write32(fWidth);
40    buffer.write32(fHeight);
41
42    SkASSERT(0 == (fProfileType & ~0xFF));
43    SkASSERT(0 == (fAlphaType & ~0xFF));
44    SkASSERT(0 == (fColorType & ~0xFF));
45    uint32_t packed = (fProfileType << 16) | (fAlphaType << 8) | fColorType;
46    buffer.write32(packed);
47}
48
49bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,
50                                  SkAlphaType* canonical) {
51    switch (colorType) {
52        case kUnknown_SkColorType:
53            alphaType = kUnknown_SkAlphaType;
54            break;
55        case kAlpha_8_SkColorType:
56            if (kUnpremul_SkAlphaType == alphaType) {
57                alphaType = kPremul_SkAlphaType;
58            }
59            // fall-through
60        case kIndex_8_SkColorType:
61        case kARGB_4444_SkColorType:
62        case kRGBA_8888_SkColorType:
63        case kBGRA_8888_SkColorType:
64        case kRGBA_F16_SkColorType:
65            if (kUnknown_SkAlphaType == alphaType) {
66                return false;
67            }
68            break;
69        case kRGB_565_SkColorType:
70        case kGray_8_SkColorType:
71            alphaType = kOpaque_SkAlphaType;
72            break;
73        default:
74            return false;
75    }
76    if (canonical) {
77        *canonical = alphaType;
78    }
79    return true;
80}
81
82///////////////////////////////////////////////////////////////////////////////////////////////////
83
84#include "SkReadPixelsRec.h"
85
86bool SkReadPixelsRec::trim(int srcWidth, int srcHeight) {
87    switch (fInfo.colorType()) {
88        case kUnknown_SkColorType:
89        case kIndex_8_SkColorType:
90            return false;
91        default:
92            break;
93    }
94    if (nullptr == fPixels || fRowBytes < fInfo.minRowBytes()) {
95        return false;
96    }
97    if (0 == fInfo.width() || 0 == fInfo.height()) {
98        return false;
99    }
100
101    int x = fX;
102    int y = fY;
103    SkIRect srcR = SkIRect::MakeXYWH(x, y, fInfo.width(), fInfo.height());
104    if (!srcR.intersect(0, 0, srcWidth, srcHeight)) {
105        return false;
106    }
107
108    // if x or y are negative, then we have to adjust pixels
109    if (x > 0) {
110        x = 0;
111    }
112    if (y > 0) {
113        y = 0;
114    }
115    // here x,y are either 0 or negative
116    fPixels = ((char*)fPixels - y * fRowBytes - x * fInfo.bytesPerPixel());
117    // the intersect may have shrunk info's logical size
118    fInfo = fInfo.makeWH(srcR.width(), srcR.height());
119    fX = srcR.x();
120    fY = srcR.y();
121
122    return true;
123}
124
125