bool SkCreateBitmapFromCGImage(SkBitmap* dst, CGImageRef image, SkISize* scaleToFit) {
    const int width = scaleToFit ? scaleToFit->width() : SkToInt(CGImageGetWidth(image));
    const int height = scaleToFit ? scaleToFit->height() : SkToInt(CGImageGetHeight(image));
    SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);

    SkBitmap tmp;
    if (!tmp.allocPixels(info)) {
        return false;
    }

    if (!SkCopyPixelsFromCGImage(tmp.info(), tmp.rowBytes(), tmp.getPixels(), image)) {
        return false;
    }

    CGImageAlphaInfo cgInfo = CGImageGetAlphaInfo(image);
    switch (cgInfo) {
        case kCGImageAlphaNone:
        case kCGImageAlphaNoneSkipLast:
        case kCGImageAlphaNoneSkipFirst:
            SkASSERT(SkBitmap::ComputeIsOpaque(tmp));
            tmp.setAlphaType(kOpaque_SkAlphaType);
            break;
        default:
            // we don't know if we're opaque or not, so compute it.
            if (SkBitmap::ComputeIsOpaque(tmp)) {
                tmp.setAlphaType(kOpaque_SkAlphaType);
            }
    }

    *dst = tmp;
    return true;
}
Exemple #2
0
bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
    CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream);

    if (NULL == imageSrc) {
        return false;
    }
    SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc);

    CGImageRef image = CGImageSourceCreateImageAtIndex(imageSrc, 0, NULL);
    if (NULL == image) {
        return false;
    }
    SkAutoTCallVProc<CGImage, CGImageRelease> arimage(image);

    const int width = SkToInt(CGImageGetWidth(image));
    const int height = SkToInt(CGImageGetHeight(image));

    bm->setInfo(SkImageInfo::MakeN32Premul(width, height));
    if (SkImageDecoder::kDecodeBounds_Mode == mode) {
        return true;
    }

    if (!this->allocPixelRef(bm, NULL)) {
        return false;
    }

    SkAutoLockPixels alp(*bm);

    if (!SkCopyPixelsFromCGImage(bm->info(), bm->rowBytes(), bm->getPixels(), image)) {
        return false;
    }

    CGImageAlphaInfo info = CGImageGetAlphaInfo(image);
    switch (info) {
        case kCGImageAlphaNone:
        case kCGImageAlphaNoneSkipLast:
        case kCGImageAlphaNoneSkipFirst:
            SkASSERT(SkBitmap::ComputeIsOpaque(*bm));
            bm->setAlphaType(kOpaque_SkAlphaType);
            break;
        default:
            // we don't know if we're opaque or not, so compute it.
            if (SkBitmap::ComputeIsOpaque(*bm)) {
                bm->setAlphaType(kOpaque_SkAlphaType);
            }
    }
    if (!bm->isOpaque() && this->getRequireUnpremultipliedColors()) {
        // CGBitmapContext does not support unpremultiplied, so the image has been premultiplied.
        // Convert to unpremultiplied.
        for (int i = 0; i < width; ++i) {
            for (int j = 0; j < height; ++j) {
                uint32_t* addr = bm->getAddr32(i, j);
                *addr = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(*addr);
            }
        }
        bm->setAlphaType(kUnpremul_SkAlphaType);
    }
    return true;
}
Exemple #3
0
void GrResourceCache::dumpStats(SkString* out) const {
    this->validate();

    int locked = fNonpurgeableResources.count();

    struct Stats {
        int fScratch;
        int fExternal;
        int fBorrowed;
        int fAdopted;
        size_t fUnbudgetedSize;

        Stats() : fScratch(0), fExternal(0), fBorrowed(0), fAdopted(0), fUnbudgetedSize(0) {}

        void update(GrGpuResource* resource) {
            if (resource->cacheAccess().isScratch()) {
                ++fScratch;
            }
            if (resource->cacheAccess().isExternal()) {
                ++fExternal;
            }
            if (resource->cacheAccess().isBorrowed()) {
                ++fBorrowed;
            }
            if (resource->cacheAccess().isAdopted()) {
                ++fAdopted;
            }
            if (!resource->resourcePriv().isBudgeted()) {
                fUnbudgetedSize += resource->gpuMemorySize();
            }
        }
    };

    Stats stats;

    for (int i = 0; i < fNonpurgeableResources.count(); ++i) {
        stats.update(fNonpurgeableResources[i]);
    }
    for (int i = 0; i < fPurgeableQueue.count(); ++i) {
        stats.update(fPurgeableQueue.at(i));
    }

    float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
    float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;

    out->appendf("Budget: %d items %d bytes\n", fMaxCount, (int)fMaxBytes);
    out->appendf("\t\tEntry Count: current %d"
                 " (%d budgeted, %d external(%d borrowed, %d adopted), %d locked, %d scratch %.2g%% full), high %d\n",
                 this->getResourceCount(), fBudgetedCount, stats.fExternal, stats.fBorrowed,
                 stats.fAdopted, locked, stats.fScratch, countUtilization, fHighWaterCount);
    out->appendf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
                 SkToInt(fBytes), SkToInt(fBudgetedBytes), byteUtilization,
                 SkToInt(stats.fUnbudgetedSize), SkToInt(fHighWaterBytes));
}
Exemple #4
0
static void excercise_draw_pos_text(SkCanvas* canvas,
                                    const char* text,
                                    SkScalar x, SkScalar y,
                                    const SkPaint& paint) {
    size_t textLen = strlen(text);
    SkAutoTArray<SkScalar> widths(SkToInt(textLen));
    paint.getTextWidths(text, textLen, &widths[0]);
    SkAutoTArray<SkPoint> pos(SkToInt(textLen));
    for (int i = 0; i < SkToInt(textLen); ++i) {
        pos[i].set(x, y);
        x += widths[i];
    }
    canvas->drawPosText(text, textLen, &pos[0], paint);
}
Exemple #5
0
void drawTestCase(SkCanvas* canvas, const char* text, SkScalar y, const SkPaint& paint) {
        SkScalar widths[kMaxStringLength];
        SkScalar posX[kMaxStringLength];
        SkPoint pos[kMaxStringLength];
        int length = SkToInt(strlen(text));
        SkASSERT(length <= kMaxStringLength);

        paint.getTextWidths(text, length, widths);

        float originX;
        switch (paint.getTextAlign()) {
            case SkPaint::kRight_Align: originX = 1; break;
            case SkPaint::kCenter_Align: originX = 0.5f; break;
            case SkPaint::kLeft_Align: originX = 0; break;
            default: SkFAIL("Invalid paint origin"); return;
        }

        float x = kTextHeight;
        for (int i = 0; i < length; ++i) {
            posX[i] = x + originX * widths[i];
            pos[i].set(posX[i], i ? pos[i - 1].y() + 3 : y + kTextHeight);
            x += widths[i];
        }

        canvas->drawPosTextH(text, length, posX, y, paint);
        canvas->drawPosText(text, length, pos, paint);
}
Exemple #6
0
void SkSVGDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
                             const SkPoint pts[], const SkPaint& paint) {
    SkPath path;

    switch (mode) {
            // todo
        case SkCanvas::kPoints_PointMode:
            SkDebugf("unsupported operation: drawPoints(kPoints_PointMode)\n");
            break;
        case SkCanvas::kLines_PointMode:
            count -= 1;
            for (size_t i = 0; i < count; i += 2) {
                path.rewind();
                path.moveTo(pts[i]);
                path.lineTo(pts[i+1]);
                AutoElement elem("path", fWriter, fResourceBucket, draw, paint);
                elem.addPathAttributes(path);
            }
            break;
        case SkCanvas::kPolygon_PointMode:
            if (count > 1) {
                path.addPoly(pts, SkToInt(count), false);
                path.moveTo(pts[0]);
                AutoElement elem("path", fWriter, fResourceBucket, draw, paint);
                elem.addPathAttributes(path);
            }
            break;
    }
}
    void onOnceBeforeDraw() override {
        for (size_t i = 0; i < SK_ARRAY_COUNT(fTallBmps); ++i) {
            int h = SkToInt((4 + i) * 1024);

            fTallBmps[i].fItemCnt = make_bm(&fTallBmps[i].fBmp, h);
        }
    }
Exemple #8
0
DEF_TEST(TextBlob_extended, reporter) {
    SkTextBlobBuilder textBlobBuilder;
    SkFont font;
    const char text1[] = "Foo";
    const char text2[] = "Bar";

    int glyphCount = font.countText(text1, strlen(text1), SkTextEncoding::kUTF8);
    SkAutoTMalloc<uint16_t> glyphs(glyphCount);
    (void)font.textToGlyphs(text1, strlen(text1), SkTextEncoding::kUTF8, glyphs.get(), glyphCount);

    auto run = SkTextBlobBuilderPriv::AllocRunText(&textBlobBuilder,
            font, glyphCount, 0, 0, SkToInt(strlen(text2)), SkString(), nullptr);
    memcpy(run.glyphs, glyphs.get(), sizeof(uint16_t) * glyphCount);
    memcpy(run.utf8text, text2, strlen(text2));
    for (int i = 0; i < glyphCount; ++i) {
        run.clusters[i] = SkTMin(SkToU32(i), SkToU32(strlen(text2)));
    }
    sk_sp<SkTextBlob> blob(textBlobBuilder.make());
    REPORTER_ASSERT(reporter, blob);

    for (SkTextBlobRunIterator it(blob.get()); !it.done(); it.next()) {
        REPORTER_ASSERT(reporter, it.glyphCount() == (uint32_t)glyphCount);
        for (uint32_t i = 0; i < it.glyphCount(); ++i) {
            REPORTER_ASSERT(reporter, it.glyphs()[i] == glyphs[i]);
        }
        REPORTER_ASSERT(reporter, SkTextBlobRunIterator::kDefault_Positioning == it.positioning());
        REPORTER_ASSERT(reporter, (SkPoint{0.0f, 0.0f}) == it.offset());
        REPORTER_ASSERT(reporter, it.textSize() > 0);
        REPORTER_ASSERT(reporter, it.clusters());
        for (uint32_t i = 0; i < it.glyphCount(); ++i) {
            REPORTER_ASSERT(reporter, i == it.clusters()[i]);
        }
        REPORTER_ASSERT(reporter, 0 == strncmp(text2, it.text(), it.textSize()));
    }
}
Exemple #9
0
    virtual void onDraw(SkCanvas* canvas) {
        // explicitly add spaces, to test a prev. bug
        const char* text = "Ham bur ge fons";
        int len = SkToInt(strlen(text));
        SkPath path;

        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setTextSize(SkIntToScalar(48));

        canvas->translate(SkIntToScalar(10), SkIntToScalar(64));

        canvas->drawText(text, len, 0, 0, paint);
        paint.getTextPath(text, len, 0, 0, &path);
        strokePath(canvas, path);
        path.reset();

        SkAutoTArray<SkPoint>  pos(len);
        SkAutoTArray<SkScalar> widths(len);
        paint.getTextWidths(text, len, &widths[0]);

        SkLCGRandom rand;
        SkScalar x = SkIntToScalar(20);
        SkScalar y = SkIntToScalar(100);
        for (int i = 0; i < len; ++i) {
            pos[i].set(x, y + rand.nextSScalar1() * 24);
            x += widths[i];
        }

        canvas->translate(0, SkIntToScalar(64));

        canvas->drawPosText(text, len, &pos[0], paint);
        paint.getPosTextPath(text, len, &pos[0], &path);
        strokePath(canvas, path);
    }
Exemple #10
0
// Returns a deterministic data of the given size that should be
// very compressible.
static SkData* new_test_data(size_t dataSize) {
    SkAutoTMalloc<uint8_t> testBuffer(dataSize);
    for (size_t i = 0; i < dataSize; ++i) {
        testBuffer[SkToInt(i)] = i % 64;
    }
    return SkData::NewFromMalloc(testBuffer.detach(), dataSize);
}
 static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
     const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcessor>();
     b->add32(SkToInt(xp.readsCoverage()) |
              (xp.getBlendFormula().fPrimaryOutputType << 1) |
              (xp.getBlendFormula().fSecondaryOutputType << 4));
     GR_STATIC_ASSERT(BlendFormula::kLast_OutputType < 8);
 };
Exemple #12
0
static size_t uni_to_utf8(const SkUnichar src[], void* dst, int count) {
    char* u8 = (char*)dst;
    for (int i = 0; i < count; ++i) {
        int n = SkToInt(SkUTF8_FromUnichar(src[i], u8));
        u8 += n;
    }
    return u8 - (char*)dst;
}
// Convert ETC1 functions to our function signatures
static bool compress_etc1_565(uint8_t* dst, const uint8_t* src,
                              int width, int height, size_t rowBytes) {
#ifndef SK_IGNORE_ETC1_SUPPORT
    return 0 == etc1_encode_image(src, width, height, 2, SkToInt(rowBytes), dst);
#else
    return false;
#endif
}
Exemple #14
0
static size_t uni_to_utf16(const SkUnichar src[], void* dst, int count) {
    uint16_t* u16 = (uint16_t*)dst;
    for (int i = 0; i < count; ++i) {
        int n = SkToInt(SkUTF16_FromUnichar(src[i], u16));
        u16 += n;
    }
    return (char*)u16 - (char*)dst;
}
Exemple #15
0
void SkPictureRecord::drawData(const void* data, size_t length) {
    // op + length + 'length' worth of data
    size_t size = 2 * kUInt32Size + SkAlign4(length);
    size_t initialOffset = this->addDraw(DRAW_DATA, &size);
    this->addInt(SkToInt(length));
    fWriter.writePad(data, length);
    this->validate(initialOffset, size);
}
SkFlattenable* SkDashPathEffect::CreateProc(SkReadBuffer& buffer) {
    const SkScalar phase = buffer.readScalar();
    uint32_t count = buffer.getArrayCount();
    SkAutoSTArray<32, SkScalar> intervals(count);
    if (buffer.readScalarArray(intervals.get(), count)) {
        return Create(intervals.get(), SkToInt(count), phase);
    }
    return nullptr;
}
Exemple #17
0
void GrResourceCache::dumpStats(SkString* out) const {
    this->validate();

    Stats stats;

    this->getStats(&stats);

    float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
    float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;

    out->appendf("Budget: %d items %d bytes\n", fMaxCount, (int)fMaxBytes);
    out->appendf("\t\tEntry Count: current %d"
                 " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n",
                 stats.fTotal, fBudgetedCount, stats.fWrapped, stats.fNumNonPurgeable,
                 stats.fScratch, countUtilization, fHighWaterCount);
    out->appendf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
                 SkToInt(fBytes), SkToInt(fBudgetedBytes), byteUtilization,
                 SkToInt(stats.fUnbudgetedSize), SkToInt(fHighWaterBytes));
}
Exemple #18
0
// called by both write() and finalize()
static void do_deflate(int flush,
                       z_stream* zStream,
                       SkWStream* out,
                       unsigned char* inBuffer,
                       size_t inBufferSize) {
    zStream->next_in = inBuffer;
    zStream->avail_in = SkToInt(inBufferSize);
    unsigned char outBuffer[SKDEFLATEWSTREAM_OUTPUT_BUFFER_SIZE];
    SkDEBUGCODE(int returnValue;)
    do {
void SkRasterPipelineBlitter::maybe_shade(int x, int y, int w) {
    if (fBurstCtx) {
        if (w > SkToInt(fShaderBuffer.size())) {
            fShaderBuffer.resize(w);
        }
        fBurstCtx->shadeSpan4f(x,y, fShaderBuffer.data(), w);
        // We'll be reading from fShaderOutput + x.
        fShaderOutput = fShaderBuffer.data() - x;
    }
}
Exemple #20
0
// ReleaseProc for SkData, assuming the data was allocated via sk_malloc, and its contents are an
// array of SkRefCnt* which need to be unref'd.
//
static void unref_all_malloc_releaseProc(const void* ptr, size_t length, void* context) {
    SkASSERT(ptr == context);   // our context is our ptr, allocated via sk_malloc
    int count = SkToInt(length / sizeof(SkRefCnt*));
    SkASSERT(count * sizeof(SkRefCnt*) == length);  // our length is snug for the array

    SkRefCnt* const* array = reinterpret_cast<SkRefCnt* const*>(ptr);
    for (int i = 0; i < count; ++i) {
        SkSafeUnref(array[i]);
    }
    sk_free(context);
}
Exemple #21
0
void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
                                   const SkPaint& paint) {
    // op + paint index + mode + count + point data
    size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
    size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
    this->addPaint(paint);

    this->addInt(mode);
    this->addInt(SkToInt(count));
    fWriter.writeMul4(pts, count * sizeof(SkPoint));
    this->validate(initialOffset, size);
}
Exemple #22
0
std::unique_ptr<SkAdvancedTypefaceMetrics> SkTestTypeface::onGetAdvancedMetrics() const { // pdf only
    std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics);
    info->fFontName.set(fTestFont->fName);
    int glyphCount = this->onCountGlyphs();

    SkTDArray<SkUnichar>& toUnicode = info->fGlyphToUnicode;
    toUnicode.setCount(glyphCount);
    SkASSERT(glyphCount == SkToInt(fTestFont->fCharCodesCount));
    for (int gid = 0; gid < glyphCount; ++gid) {
        toUnicode[gid] = SkToS32(fTestFont->fCharCodes[gid]);
    }
    return info;
}
Exemple #23
0
static SkString pdf_date(const SkTime::DateTime& dt) {
    int timeZoneMinutes = SkToInt(dt.fTimeZoneMinutes);
    char timezoneSign = timeZoneMinutes >= 0 ? '+' : '-';
    int timeZoneHours = SkTAbs(timeZoneMinutes) / 60;
    timeZoneMinutes = SkTAbs(timeZoneMinutes) % 60;
    return SkStringPrintf(
            "D:%04u%02u%02u%02u%02u%02u%c%02d'%02d'",
            static_cast<unsigned>(dt.fYear), static_cast<unsigned>(dt.fMonth),
            static_cast<unsigned>(dt.fDay), static_cast<unsigned>(dt.fHour),
            static_cast<unsigned>(dt.fMinute),
            static_cast<unsigned>(dt.fSecond), timezoneSign, timeZoneHours,
            timeZoneMinutes);
}
Exemple #24
0
void SkTime::DateTime::toISO8601(SkString* dst) const {
    if (dst) {
        int timeZoneMinutes = SkToInt(fTimeZoneMinutes);
        char timezoneSign = timeZoneMinutes >= 0 ? '+' : '-';
        int timeZoneHours = SkTAbs(timeZoneMinutes) / 60;
        timeZoneMinutes = SkTAbs(timeZoneMinutes) % 60;
        dst->printf("%04u-%02u-%02uT%02u:%02u:%02u%c%02d:%02d",
                    static_cast<unsigned>(fYear), static_cast<unsigned>(fMonth),
                    static_cast<unsigned>(fDay), static_cast<unsigned>(fHour),
                    static_cast<unsigned>(fMinute),
                    static_cast<unsigned>(fSecond), timezoneSign, timeZoneHours,
                    timeZoneMinutes);
    }
}
GrPathRange* GrGLPathRendering::createGlyphs(const SkTypeface* typeface,
                                             const SkDescriptor* desc,
                                             const SkStrokeRec& stroke) {
    if (NULL != desc || !caps().glyphLoadingSupport) {
        return GrPathRendering::createGlyphs(typeface, desc, stroke);
    }

    if (NULL == typeface) {
        typeface = SkTypeface::GetDefaultTypeface();
        SkASSERT(NULL != typeface);
    }

    int faceIndex;
    SkAutoTDelete<SkStream> fontStream(typeface->openStream(&faceIndex));

    const size_t fontDataLength = fontStream->getLength();
    if (0 == fontDataLength) {
        return GrPathRendering::createGlyphs(typeface, NULL, stroke);
    }

    SkTArray<uint8_t> fontTempBuffer;
    const void* fontData = fontStream->getMemoryBase();
    if (NULL == fontData) {
        // TODO: Find a more efficient way to pass the font data (e.g. open file descriptor).
        fontTempBuffer.reset(SkToInt(fontDataLength));
        fontStream->read(&fontTempBuffer.front(), fontDataLength);
        fontData = &fontTempBuffer.front();
    }

    const int numPaths = typeface->countGlyphs();
    const GrGLuint basePathID = this->genPaths(numPaths);
    SkAutoTUnref<GrGLPath> templatePath(SkNEW_ARGS(GrGLPath, (fGpu, SkPath(), stroke)));

    GrGLenum status;
    GL_CALL_RET(status, PathMemoryGlyphIndexArray(basePathID, GR_GL_STANDARD_FONT_FORMAT,
                                                  fontDataLength, fontData, faceIndex, 0,
                                                  numPaths, templatePath->pathID(),
                                                  SkPaint::kCanonicalTextSizeForPaths));

    if (GR_GL_FONT_GLYPHS_AVAILABLE != status) {
        this->deletePaths(basePathID, numPaths);
        return GrPathRendering::createGlyphs(typeface, NULL, stroke);
    }

    // This is a crude approximation. We may want to consider giving this class
    // a pseudo PathGenerator whose sole purpose is to track the approximate gpu
    // memory size.
    const size_t gpuMemorySize = fontDataLength / 4;
    return SkNEW_ARGS(GrGLPathRange, (fGpu, basePathID, numPaths, gpuMemorySize, stroke));
}
Exemple #26
0
void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
                                   const SkPaint& paint) {
    fContentInfo.onDrawPoints(count, paint);

    // op + paint index + mode + count + point data
    size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
    size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
    SkASSERT(initialOffset+get_paint_offset(DRAW_POINTS, size) == fWriter.bytesWritten());
    this->addPaint(paint);

    this->addInt(mode);
    this->addInt(SkToInt(count));
    fWriter.writeMul4(pts, count * sizeof(SkPoint));
    this->validate(initialOffset, size);
}
Exemple #27
0
sk_sp<SkFlattenable> SkDashImpl::CreateProc(SkReadBuffer& buffer) {
    const SkScalar phase = buffer.readScalar();
    uint32_t count = buffer.getArrayCount();

    // Don't allocate gigantic buffers if there's not data for them.
    if (count > buffer.size() / sizeof(SkScalar)) {
        return nullptr;
    }

    SkAutoSTArray<32, SkScalar> intervals(count);
    if (buffer.readScalarArray(intervals.get(), count)) {
        return SkDashPathEffect::Make(intervals.get(), SkToInt(count), phase);
    }
    return nullptr;
}
Exemple #28
0
 SkRect draw(SkCanvas* canvas, const SkPaint& paint) override {
     SkRandom random;
     SkPoint points[500];
     SkRect bounds = SkRect::MakeWH(50, 50);
     int count = SkToInt(SK_ARRAY_COUNT(points));
     if (SkCanvas::kPoints_PointMode != fMode) {
         count = SkTMin(count, 10);
     }
     for (int p = 0; p < count; ++p) {
         points[p].fX = random.nextUScalar1() * bounds.width();
         points[p].fY = random.nextUScalar1() * bounds.width();
     }
     canvas->drawPoints(fMode, count, points, paint);
     return bounds;
 }
Exemple #29
0
void SkErrorInternals::SetError(SkError code, const char *fmt, ...) {
    THREAD_ERROR = code;
    va_list args;

    char *str = THREAD_ERROR_STRING;
    const char *error_name = NULL;
    switch( code ) {
        case kNoError_SkError:
            error_name = "No Error";
            break;
        case kInvalidArgument_SkError:
            error_name = "Invalid Argument";
            break;
        case kInvalidOperation_SkError:
            error_name = "Invalid Operation";
            break;
        case kInvalidHandle_SkError:
            error_name = "Invalid Handle";
            break;
        case kInvalidPaint_SkError:
            error_name = "Invalid Paint";
            break;
        case kOutOfMemory_SkError:
            error_name = "Out Of Memory";
            break;
        case kParseError_SkError:
            error_name = "Parse Error";
            break;
        default:
            error_name = "Unknown error";
            break;
    }

    sprintf( str, "%s: ", error_name );
    int string_left = SkToInt(ERROR_STRING_LENGTH - strlen(str));
    str += strlen(str);

    va_start( args, fmt );
    vsnprintf( str, string_left, fmt, args );
    va_end( args );
    SkErrorCallbackFunction fn = THREAD_ERROR_CALLBACK;
    if (fn && code != kNoError_SkError) {
        fn(code, THREAD_ERROR_CONTEXT);
    }
}
Exemple #30
0
// Sanity checks for the GetDateTime function.
DEF_TEST(Time_GetDateTime, r) {
    SkTime::DateTime dateTime;
    SkTime::GetDateTime(&dateTime);

    // TODO(future generation): update these values.
    const uint16_t kMinimumSaneYear = 1964;
    const uint16_t kMaximumSaneYear = 2064;

    if (dateTime.fYear < kMinimumSaneYear) {
        ERRORF(r,
               "SkTime::GetDateTime: %u (CurrentYear) < %u (MinimumSaneYear)",
               static_cast<unsigned>(dateTime.fYear),
               static_cast<unsigned>(kMinimumSaneYear));
    }
    if (dateTime.fYear > kMaximumSaneYear) {
        ERRORF(r,
               "SkTime::GetDateTime: %u (CurrentYear) > %u (MaximumSaneYear)",
               static_cast<unsigned>(dateTime.fYear),
               static_cast<unsigned>(kMaximumSaneYear));
    }

    REPORTER_ASSERT(r, dateTime.fMonth >= 1);
    REPORTER_ASSERT(r, dateTime.fMonth <= 12);

    REPORTER_ASSERT(r, dateTime.fDay >= 1);
    REPORTER_ASSERT(r, dateTime.fDay <= 31);

    REPORTER_ASSERT(r, dateTime.fHour <= 23);

    REPORTER_ASSERT(r, dateTime.fMinute <= 59);

    REPORTER_ASSERT(r, dateTime.fSecond <= 60);  // leap seconds are 23:59:60

    // The westernmost timezone is -12:00.
    // The easternmost timezone is +14:00.
    REPORTER_ASSERT(r, SkTAbs(SkToInt(dateTime.fTimeZoneMinutes)) <= 14 * 60);

    SkString timeStamp;
    dateTime.toISO8601(&timeStamp);
    REPORTER_ASSERT(r, timeStamp.size() > 0);
    INFOF(r, "\nCurrent Time (ISO-8601 format): \"%s\"\n",
          timeStamp.c_str());
}