Beispiel #1
0
bool SkImageGenerator::tryGenerateBitmap(SkBitmap* bitmap, const SkImageInfo* infoPtr) {
    const SkImageInfo info = infoPtr ? *infoPtr : this->getInfo();
    const size_t rowBytes = info.minRowBytes();
    const size_t pixelSize = info.getSafeSize(rowBytes);
    if (0 == pixelSize) {
        return false;
    }

    SkAutoFree pixelStorage(sk_malloc_flags(pixelSize, 0));
    void* pixels = pixelStorage.get();
    if (!pixels) {
        return false;
    }
    
    SkPMColor ctStorage[256];
    int ctCount = 0;
    
    if (!this->getPixels(info, pixels, rowBytes, ctStorage, &ctCount)) {
        return false;
    }
    
    SkAutoTUnref<SkColorTable> ctable;
    if (ctCount > 0) {
        SkASSERT(kIndex_8_SkColorType == info.colorType());
        ctable.reset(new SkColorTable(ctStorage, ctCount));
    } else {
        SkASSERT(kIndex_8_SkColorType != info.colorType());
    }
    
    return bitmap->installPixels(info, pixelStorage.detach(), rowBytes, ctable,
                                 release_malloc_proc, nullptr);
}
SkTypeface* SkTypeface::Deserialize(SkStream* stream) {
    SkFontDescriptor desc(stream);
    size_t length = stream->readPackedUInt();
    if (length > 0) {
        void* addr = sk_malloc_flags(length, 0);
        if (addr) {
            SkAutoTUnref<SkMemoryStream> localStream(SkNEW(SkMemoryStream));
            localStream->setMemoryOwned(addr, length);

            if (stream->read(addr, length) == length) {
                return SkTypeface::CreateFromStream(localStream.get());
            } else {
                // Failed to read the full font data, so fall through and try to create from name.
                // If this is because of EOF, all subsequent reads from the stream will be EOF.
                // If this is because of a stream error, the stream is in an error state,
                // do not attempt to skip any remaining bytes.
            }
        } else {
            // failed to allocate, so just skip and create-from-name
            stream->skip(length);
        }
    }

    return SkTypeface::CreateFromName(desc.getFamilyName(), desc.getStyle());
}
Beispiel #3
0
bool SkRgnBuilder::init(int maxHeight, int maxTransitions) {
    if ((maxHeight | maxTransitions) < 0) {
        return false;
    }

    Sk64 count, size;

    // compute the count with +1 and +3 slop for the working buffer
    count.setMul(maxHeight + 1, 3 + maxTransitions);
    if (!count.is32() || count.isNeg()) {
        return false;
    }
    fStorageCount = count.get32();

    size.setMul(fStorageCount, sizeof(SkRegion::RunType));
    if (!size.is32() || size.isNeg()) {
        return false;
    }

    fStorage = (SkRegion::RunType*)sk_malloc_flags(size.get32(), 0);
    if (NULL == fStorage) {
        return false;
    }

    fCurrScanline = NULL;    // signal empty collection
    fPrevScanline = NULL;    // signal first scanline
    return true;
}
Beispiel #4
0
/** We explicitly use this allocator for SkBimap pixels, so that we can
    freely assign memory allocated by one class to the other.
*/
uint8_t* SkMask::AllocImage(size_t size, AllocType at) {
    size_t aligned_size = SkSafeMath::Align4(size);
    unsigned flags = SK_MALLOC_THROW;
    if (at == kZeroInit_Alloc) {
        flags |= SK_MALLOC_ZERO_INITIALIZE;
    }
    return static_cast<uint8_t*>(sk_malloc_flags(aligned_size, flags));
}
GrGLBufferImpl::GrGLBufferImpl(GrGpuGL* gpu, const Desc& desc, GrGLenum bufferType)
    : fDesc(desc)
    , fBufferType(bufferType)
    , fLockPtr(NULL) {
    if (0 == desc.fID) {
        fCPUData = sk_malloc_flags(desc.fSizeInBytes, SK_MALLOC_THROW);
    } else {
        fCPUData = NULL;
    }
    VALIDATE();
}
Beispiel #6
0
bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
                                  SkColorTable* ctable, bool reportSizeToVM) {
    Sk64 size64 = bitmap->getSize64();
    if (size64.isNeg() || !size64.is32()) {
        doThrow(env, "java/lang/IllegalArgumentException",
                     "bitmap size exceeds 32bits");
        return false;
    }
    
    size_t size = size64.get32();
    jlong jsize = size;  // the VM wants longs for the size
    if (reportSizeToVM) {
        //    SkDebugf("-------------- inform VM we've allocated %d bytes\n", size);
        bool r = env->CallBooleanMethod(gVMRuntime_singleton,
                                    gVMRuntime_trackExternalAllocationMethodID,
                                    jsize);
        if (GraphicsJNI::hasException(env)) {
            return false;
        }
        if (!r) {
            LOGE("VM won't let us allocate %zd bytes\n", size);
            doThrowOOME(env, "bitmap size exceeds VM budget");
            return false;
        }
    }
    // call the version of malloc that returns null on failure
    void* addr = sk_malloc_flags(size, 0);
    if (NULL == addr) {
        if (reportSizeToVM) {
            //        SkDebugf("-------------- inform VM we're releasing %d bytes which we couldn't allocate\n", size);
            // we didn't actually allocate it, so inform the VM
            env->CallVoidMethod(gVMRuntime_singleton,
                                 gVMRuntime_trackExternalFreeMethodID,
                                 jsize);
            if (!GraphicsJNI::hasException(env)) {
                doThrowOOME(env, "bitmap size too large for malloc");
            }
        }
        return false;
    }
    
    SkPixelRef* pr = reportSizeToVM ?
                        new AndroidPixelRef(env, addr, size, ctable) :
                        new SkMallocPixelRef(addr, size, ctable);
    bitmap->setPixelRef(pr)->unref();
    // since we're already allocated, we lockPixels right away
    // HeapAllocator behaves this way too
    bitmap->lockPixels();
    return true;
}
GrGLBufferImpl::GrGLBufferImpl(GrGpuGL* gpu, const Desc& desc, GrGLenum bufferType)
    : fDesc(desc)
    , fBufferType(bufferType)
    , fMapPtr(NULL) {
    if (0 == desc.fID) {
        fCPUData = sk_malloc_flags(desc.fSizeInBytes, SK_MALLOC_THROW);
        fGLSizeInBytes = 0;
    } else {
        fCPUData = NULL;
        // We assume that the GL buffer was created at the desc's size initially.
        fGLSizeInBytes = fDesc.fSizeInBytes;
    }
    VALIDATE();
}
Beispiel #8
0
bool SkAutoPixmapStorage::tryAlloc(const SkImageInfo& info) {
    this->freeStorage();

    size_t rb;
    size_t size = AllocSize(info, &rb);
    if (0 == size) {
        return false;
    }
    void* pixels = sk_malloc_flags(size, 0);
    if (nullptr == pixels) {
        return false;
    }
    this->reset(info, pixels, rb);
    fStorage = pixels;
    return true;
}
static sk_sp<SkData>
MakeSkData(unsigned char* aData, const IntSize& aSize, int32_t aStride)
{
  CheckedInt<size_t> size = aStride;
  size *= aSize.height;
  if (size.isValid()) {
    void* mem = sk_malloc_flags(size.value(), 0);
    if (mem) {
      if (aData) {
        memcpy(mem, aData, size.value());
      }
      return SkData::MakeFromMalloc(mem, size.value());
    }
  }
  return nullptr;
}
void SkPDFDevice::drawPosText(const SkDraw&, const void* text, size_t len,
                              const SkScalar pos[], SkScalar constY,
                              int scalarsPerPos, const SkPaint& paint) {
    SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos);
    SkPaint textPaint = calculateTextPaint(paint);
    updateGSFromPaint(textPaint, true);

    // Make sure we have a glyph id encoding.
    SkAutoFree glyphStorage;
    uint16_t* glyphIDs;
    size_t numGlyphs;
    if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) {
        numGlyphs = paint.textToGlyphs(text, len, NULL);
        glyphIDs = (uint16_t*)sk_malloc_flags(numGlyphs * 2,
                                              SK_MALLOC_TEMP | SK_MALLOC_THROW);
        glyphStorage.set(glyphIDs);
        paint.textToGlyphs(text, len, glyphIDs);
        textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    } else {
        SkASSERT((len & 1) == 0);
        numGlyphs = len / 2;
        glyphIDs = (uint16_t*)text;
    }

    SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
    fContent.writeText("BT\n");
    updateFont(textPaint, glyphIDs[0]);
    for (size_t i = 0; i < numGlyphs; i++) {
        SkPDFFont* font = fGraphicStack[fGraphicStackIndex].fFont;
        uint16_t encodedValue = glyphIDs[i];
        if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) {
            updateFont(textPaint, glyphIDs[i]);
            i--;
            continue;
        }
        SkScalar x = pos[i * scalarsPerPos];
        SkScalar y = scalarsPerPos == 1 ? constY : pos[i * scalarsPerPos + 1];
        alignText(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y, NULL);
        setTextTransform(x, y, textPaint.getTextSkewX());
        SkString encodedString =
            SkPDFString::formatString(&encodedValue, 1,
                                      font->multiByteGlyphs());
        fContent.writeText(encodedString.c_str());
        fContent.writeText(" Tj\n");
    }
    fContent.writeText("ET\n");
}
Beispiel #11
0
GrGLBufferImpl::GrGLBufferImpl(GrGLGpu* gpu, const Desc& desc, GrGLenum bufferType)
    : fDesc(desc)
    , fBufferType(bufferType)
    , fMapPtr(nullptr) {
    if (0 == desc.fID) {
        if (gpu->caps()->mustClearUploadedBufferData()) {
            fCPUData = sk_calloc_throw(desc.fSizeInBytes);
        } else {
            fCPUData = sk_malloc_flags(desc.fSizeInBytes, SK_MALLOC_THROW);
        }
        fGLSizeInBytes = 0;
    } else {
        fCPUData = nullptr;
        // We assume that the GL buffer was created at the desc's size initially.
        fGLSizeInBytes = fDesc.fSizeInBytes;
    }
    VALIDATE();
}
Beispiel #12
0
GrGLBuffer::GrGLBuffer(GrGLGpu* gpu, size_t size, GrBufferType intendedType,
                       GrAccessPattern accessPattern, bool cpuBacked, const void* data)
    : INHERITED(gpu, size, intendedType, accessPattern, cpuBacked),
      fCPUData(nullptr),
      fIntendedType(intendedType),
      fBufferID(0),
      fSizeInBytes(size),
      fUsage(gr_to_gl_access_pattern(intendedType, accessPattern)),
      fGLSizeInBytes(0),
      fHasAttachedToTexture(false) {
    if (this->isCPUBacked()) {
        // Core profile uses vertex array objects, which disallow client side arrays.
        SkASSERT(!gpu->glCaps().isCoreProfile());
        if (gpu->caps()->mustClearUploadedBufferData()) {
            fCPUData = sk_calloc_throw(fSizeInBytes);
        } else {
            fCPUData = sk_malloc_flags(fSizeInBytes, SK_MALLOC_THROW);
        }
        if (data) {
            memcpy(fCPUData, data, fSizeInBytes);
        }
    } else {
        GL_CALL(GenBuffers(1, &fBufferID));
        if (fBufferID) {
            GrGLenum target = gpu->bindBuffer(fIntendedType, this);
            CLEAR_ERROR_BEFORE_ALLOC(gpu->glInterface());
            // make sure driver can allocate memory for this buffer
            GL_ALLOC_CALL(gpu->glInterface(), BufferData(target,
                                                         (GrGLsizeiptr) fSizeInBytes,
                                                         data,
                                                         fUsage));
            if (CHECK_ALLOC_ERROR(gpu->glInterface()) != GR_GL_NO_ERROR) {
                GL_CALL(DeleteBuffers(1, &fBufferID));
                fBufferID = 0;
            } else {
                fGLSizeInBytes = fSizeInBytes;
            }
        }
    }
    VALIDATE();
    this->registerWithCache(SkBudgeted::kYes);
}
Beispiel #13
0
bool SkRgnBuilder::init(int maxHeight, int maxTransitions, bool pathIsInverse) {
    if ((maxHeight | maxTransitions) < 0) {
        return false;
    }

    Sk64 count, size;

    if (pathIsInverse) {
        // allow for additional X transitions to "invert" each scanline
        // [ L' ... normal transitions ... R' ]
        //
        maxTransitions += 2;
    }

    // compute the count with +1 and +3 slop for the working buffer
    count.setMul(maxHeight + 1, 3 + maxTransitions);

    if (pathIsInverse) {
        // allow for two "empty" rows for the top and bottom
        //      [ Y, 1, L, R, S] == 5 (*2 for top and bottom)
        count.add(10);
    }

    if (!count.is32() || count.isNeg()) {
        return false;
    }
    fStorageCount = count.get32();

    size.setMul(fStorageCount, sizeof(SkRegion::RunType));
    if (!size.is32() || size.isNeg()) {
        return false;
    }

    fStorage = (SkRegion::RunType*)sk_malloc_flags(size.get32(), 0);
    if (NULL == fStorage) {
        return false;
    }

    fCurrScanline = NULL;    // signal empty collection
    fPrevScanline = NULL;    // signal first scanline
    return true;
}
SkData* DecodingImageGenerator::refEncodedData() {
    // This functionality is used in `gm --serialize`
    // Does not encode options.
    if (fData != NULL) {
        return SkSafeRef(fData);
    }
    // TODO(halcanary): SkStreamRewindable needs a refData() function
    // which returns a cheap copy of the underlying data.
    if (!fStream->rewind()) {
        return NULL;
    }
    size_t length = fStream->getLength();
    if (0 == length) {
        return NULL;
    }
    void* buffer = sk_malloc_flags(length, 0);
    SkCheckResult(fStream->read(buffer, length), length);
    fData = SkData::NewFromMalloc(buffer, length);
    return SkSafeRef(fData);
}
SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) {
    size_t size = bytes;
    if (size < fChunkSize) {
        size = fChunkSize;
    }

    Block* block = (Block*)sk_malloc_flags(sizeof(Block) + size,
                        ftype == kThrow_AllocFailType ? SK_MALLOC_THROW : 0);

    if (block) {
        //    block->fNext = fBlock;
        block->fFreeSize = size;
        block->fFreePtr = block->startOfData();

        fTotalCapacity += size;
        fBlockCount += 1;

        fChunkSize = increase_next_size(fChunkSize);
    }
    return block;
}
Beispiel #16
0
bool SkRgnBuilder::init(int maxHeight, int maxTransitions, bool pathIsInverse) {
    if ((maxHeight | maxTransitions) < 0) {
        return false;
    }

    if (pathIsInverse) {
        // allow for additional X transitions to "invert" each scanline
        // [ L' ... normal transitions ... R' ]
        //
        maxTransitions += 2;
    }

    // compute the count with +1 and +3 slop for the working buffer
    int64_t count = sk_64_mul(maxHeight + 1, 3 + maxTransitions);

    if (pathIsInverse) {
        // allow for two "empty" rows for the top and bottom
        //      [ Y, 1, L, R, S] == 5 (*2 for top and bottom)
        count += 10;
    }

    if (count < 0 || !sk_64_isS32(count)) {
        return false;
    }
    fStorageCount = sk_64_asS32(count);

    int64_t size = sk_64_mul(fStorageCount, sizeof(SkRegion::RunType));
    if (size < 0 || !sk_64_isS32(size)) {
        return false;
    }

    fStorage = (SkRegion::RunType*)sk_malloc_flags(sk_64_asS32(size), 0);
    if (NULL == fStorage) {
        return false;
    }

    fCurrScanline = NULL;    // signal empty collection
    fPrevScanline = NULL;    // signal first scanline
    return true;
}
SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) {
    Block* block = fPool;

    if (block && bytes <= block->fFreeSize) {
        fPool = block->fNext;
        return block;
    }

    size_t  size = SkMax32((int32_t)bytes, (int32_t)fMinSize);

    block = (Block*)sk_malloc_flags(sizeof(Block) + size,
                        ftype == kThrow_AllocFailType ? SK_MALLOC_THROW : 0);

    if (block) {
        //    block->fNext = fBlock;
        block->fFreeSize = size;
        block->fFreePtr = block->startOfData();
        
        fTotalCapacity += size;
    }
    return block;
}
Beispiel #18
0
SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
                                                size_t requestedRowBytes,
                                                SkColorTable* ctable) {
    if (!is_valid(info, ctable)) {
        return NULL;
    }

    int32_t minRB = SkToS32(info.minRowBytes());
    if (minRB < 0) {
        return NULL;    // allocation will be too large
    }
    if (requestedRowBytes > 0 && (int32_t)requestedRowBytes < minRB) {
        return NULL;    // cannot meet requested rowbytes
    }

    int32_t rowBytes;
    if (requestedRowBytes) {
        rowBytes = SkToS32(requestedRowBytes);
    } else {
        rowBytes = minRB;
    }

    int64_t bigSize = (int64_t)info.fHeight * rowBytes;
    if (!sk_64_isS32(bigSize)) {
        return NULL;
    }

    size_t size = sk_64_asS32(bigSize);
    SkASSERT(size >= info.getSafeSize(rowBytes));
    void* addr = sk_malloc_flags(size, 0);
    if (NULL == addr) {
        return NULL;
    }

    return SkNEW_ARGS(SkMallocPixelRef,
                      (info, addr, rowBytes, ctable,
                       sk_free_releaseproc, NULL));
}
SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
                                                size_t requestedRowBytes,
                                                SkColorTable* ctable) {
    if (!is_valid(info, ctable)) {
        return NULL;
    }

    int32_t minRB = info.minRowBytes();
    if (minRB < 0) {
        return NULL;    // allocation will be too large
    }
    if (requestedRowBytes > 0 && (int32_t)requestedRowBytes < minRB) {
        return NULL;    // cannot meet requested rowbytes
    }

    int32_t rowBytes;
    if (requestedRowBytes) {
        rowBytes = requestedRowBytes;
    } else {
        rowBytes = minRB;
    }

    Sk64 bigSize;
    bigSize.setMul(info.fHeight, rowBytes);
    if (!bigSize.is32()) {
        return NULL;
    }

    size_t size = bigSize.get32();
    void* addr = sk_malloc_flags(size, 0);
    if (NULL == addr) {
        return NULL;
    }

    return SkNEW_ARGS(SkMallocPixelRef, (info, addr, rowBytes, ctable, true));
}
sk_sp<SkPixelRef> SkMallocPixelRef::MakeAllocate(const SkImageInfo& info,
                                                size_t rowBytes,
                                                sk_sp<SkColorTable> ctable) {
    auto sk_malloc_nothrow = [](size_t size) { return sk_malloc_flags(size, 0); };
    return MakeUsing(sk_malloc_nothrow, info, rowBytes, std::move(ctable));
}
Beispiel #21
0
SkCodec* SkIcoCodec::NewFromStream(SkStream* stream, Result* result) {
    // Ensure that we do not leak the input stream
    std::unique_ptr<SkStream> inputStream(stream);

    // Header size constants
    static const uint32_t kIcoDirectoryBytes = 6;
    static const uint32_t kIcoDirEntryBytes = 16;

    // Read the directory header
    std::unique_ptr<uint8_t[]> dirBuffer(new uint8_t[kIcoDirectoryBytes]);
    if (inputStream.get()->read(dirBuffer.get(), kIcoDirectoryBytes) !=
            kIcoDirectoryBytes) {
        SkCodecPrintf("Error: unable to read ico directory header.\n");
        *result = kIncompleteInput;
        return nullptr;
    }

    // Process the directory header
    const uint16_t numImages = get_short(dirBuffer.get(), 4);
    if (0 == numImages) {
        SkCodecPrintf("Error: No images embedded in ico.\n");
        *result = kInvalidInput;
        return nullptr;
    }

    // This structure is used to represent the vital information about entries
    // in the directory header.  We will obtain this information for each
    // directory entry.
    struct Entry {
        uint32_t offset;
        uint32_t size;
    };
    SkAutoFree dirEntryBuffer(sk_malloc_flags(sizeof(Entry) * numImages,
                                              SK_MALLOC_TEMP));
    if (!dirEntryBuffer) {
        SkCodecPrintf("Error: OOM allocating ICO directory for %i images.\n",
                      numImages);
        *result = kInternalError;
        return nullptr;
    }
    auto* directoryEntries = reinterpret_cast<Entry*>(dirEntryBuffer.get());

    // Iterate over directory entries
    for (uint32_t i = 0; i < numImages; i++) {
        uint8_t entryBuffer[kIcoDirEntryBytes];
        if (inputStream->read(entryBuffer, kIcoDirEntryBytes) !=
                kIcoDirEntryBytes) {
            SkCodecPrintf("Error: Dir entries truncated in ico.\n");
            *result = kIncompleteInput;
            return nullptr;
        }

        // The directory entry contains information such as width, height,
        // bits per pixel, and number of colors in the color palette.  We will
        // ignore these fields since they are repeated in the header of the
        // embedded image.  In the event of an inconsistency, we would always
        // defer to the value in the embedded header anyway.

        // Specifies the size of the embedded image, including the header
        uint32_t size = get_int(entryBuffer, 8);

        // Specifies the offset of the embedded image from the start of file.
        // It does not indicate the start of the pixel data, but rather the
        // start of the embedded image header.
        uint32_t offset = get_int(entryBuffer, 12);

        // Save the vital fields
        directoryEntries[i].offset = offset;
        directoryEntries[i].size = size;
    }

    // Default Result, if no valid embedded codecs are found.
    *result = kInvalidInput;

    // It is "customary" that the embedded images will be stored in order of
    // increasing offset.  However, the specification does not indicate that
    // they must be stored in this order, so we will not trust that this is the
    // case.  Here we sort the embedded images by increasing offset.
    struct EntryLessThan {
        bool operator() (Entry a, Entry b) const {
            return a.offset < b.offset;
        }
    };
    EntryLessThan lessThan;
    SkTQSort(directoryEntries, &directoryEntries[numImages - 1], lessThan);

    // Now will construct a candidate codec for each of the embedded images
    uint32_t bytesRead = kIcoDirectoryBytes + numImages * kIcoDirEntryBytes;
    std::unique_ptr<SkTArray<std::unique_ptr<SkCodec>, true>> codecs(
            new (SkTArray<std::unique_ptr<SkCodec>, true>)(numImages));
    for (uint32_t i = 0; i < numImages; i++) {
        uint32_t offset = directoryEntries[i].offset;
        uint32_t size = directoryEntries[i].size;

        // Ensure that the offset is valid
        if (offset < bytesRead) {
            SkCodecPrintf("Warning: invalid ico offset.\n");
            continue;
        }

        // If we cannot skip, assume we have reached the end of the stream and
        // stop trying to make codecs
        if (inputStream.get()->skip(offset - bytesRead) != offset - bytesRead) {
            SkCodecPrintf("Warning: could not skip to ico offset.\n");
            break;
        }
        bytesRead = offset;

        // Create a new stream for the embedded codec
        SkAutoFree buffer(sk_malloc_flags(size, 0));
        if (!buffer) {
            SkCodecPrintf("Warning: OOM trying to create embedded stream.\n");
            break;
        }

        if (inputStream->read(buffer.get(), size) != size) {
            SkCodecPrintf("Warning: could not create embedded stream.\n");
            *result = kIncompleteInput;
            break;
        }

        sk_sp<SkData> data(SkData::MakeFromMalloc(buffer.release(), size));
        std::unique_ptr<SkMemoryStream> embeddedStream(new SkMemoryStream(data));
        bytesRead += size;

        // Check if the embedded codec is bmp or png and create the codec
        SkCodec* codec = nullptr;
        Result dummyResult;
        if (SkPngCodec::IsPng((const char*) data->bytes(), data->size())) {
            codec = SkPngCodec::NewFromStream(embeddedStream.release(), &dummyResult);
        } else {
            codec = SkBmpCodec::NewFromIco(embeddedStream.release(), &dummyResult);
        }

        // Save a valid codec
        if (nullptr != codec) {
            codecs->push_back().reset(codec);
        }
    }

    // Recognize if there are no valid codecs
    if (0 == codecs->count()) {
        SkCodecPrintf("Error: could not find any valid embedded ico codecs.\n");
        return nullptr;
    }

    // Use the largest codec as a "suggestion" for image info
    size_t maxSize = 0;
    int maxIndex = 0;
    for (int i = 0; i < codecs->count(); i++) {
        SkImageInfo info = codecs->operator[](i)->getInfo();
        size_t size = info.getSafeSize(info.minRowBytes());

        if (size > maxSize) {
            maxSize = size;
            maxIndex = i;
        }
    }
    int width = codecs->operator[](maxIndex)->getInfo().width();
    int height = codecs->operator[](maxIndex)->getInfo().height();
    SkEncodedInfo info = codecs->operator[](maxIndex)->getEncodedInfo();
    SkColorSpace* colorSpace = codecs->operator[](maxIndex)->getInfo().colorSpace();

    *result = kSuccess;
    // The original stream is no longer needed, because the embedded codecs own their
    // own streams.
    return new SkIcoCodec(width, height, info, codecs.release(), sk_ref_sp(colorSpace));
}
Beispiel #22
0
 static Block* Alloc(Block* prev, size_t size, unsigned flags) {
     SkASSERT(size >= sizeof(Block));
     Block* b = (Block*)sk_malloc_flags(size, flags);
     b->prev = prev;
     return b;
 }
void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
                           SkScalar x, SkScalar y, const SkPaint& paint) {
    SkPaint textPaint = calculateTextPaint(paint);
    updateGSFromPaint(textPaint, true);

    // We want the text in glyph id encoding and a writable buffer, so we end
    // up making a copy either way.
    size_t numGlyphs = paint.textToGlyphs(text, len, NULL);
    uint16_t* glyphIDs =
        (uint16_t*)sk_malloc_flags(numGlyphs * 2,
                                   SK_MALLOC_TEMP | SK_MALLOC_THROW);
    SkAutoFree autoFreeGlyphIDs(glyphIDs);
    if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) {
        paint.textToGlyphs(text, len, glyphIDs);
        textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    } else {
        SkASSERT((len & 1) == 0);
        SkASSERT(len / 2 == numGlyphs);
        memcpy(glyphIDs, text, len);
    }

    SkScalar width;
    SkScalar* widthPtr = NULL;
    if (textPaint.isUnderlineText() || textPaint.isStrikeThruText())
        widthPtr = &width;

    SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
    alignText(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y, widthPtr);
    fContent.writeText("BT\n");
    setTextTransform(x, y, textPaint.getTextSkewX());
    size_t consumedGlyphCount = 0;
    while (numGlyphs > consumedGlyphCount) {
        updateFont(textPaint, glyphIDs[consumedGlyphCount]);
        SkPDFFont* font = fGraphicStack[fGraphicStackIndex].fFont;
        size_t availableGlyphs =
            font->glyphsToPDFFontEncoding(glyphIDs + consumedGlyphCount,
                                          numGlyphs - consumedGlyphCount);
        SkString encodedString =
            SkPDFString::formatString(glyphIDs + consumedGlyphCount,
                                      availableGlyphs, font->multiByteGlyphs());
        fContent.writeText(encodedString.c_str());
        consumedGlyphCount += availableGlyphs;
        fContent.writeText(" Tj\n");
    }
    fContent.writeText("ET\n");

    // Draw underline and/or strikethrough if the paint has them.
    // drawPosText() and drawTextOnPath() don't draw underline or strikethrough
    // because the raster versions don't.  Use paint instead of textPaint
    // because we may have changed strokeWidth to do fakeBold text.
    if (paint.isUnderlineText() || paint.isStrikeThruText()) {
        SkScalar textSize = paint.getTextSize();
        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);

        if (paint.isUnderlineText()) {
            SkScalar top = SkScalarMulAdd(textSize, kStdUnderline_Offset, y);
            SkRect r = SkRect::MakeXYWH(x, top - height, width, height);
            drawRect(d, r, paint);
        }
        if (paint.isStrikeThruText()) {
            SkScalar top = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, y);
            SkRect r = SkRect::MakeXYWH(x, top - height, width, height);
            drawRect(d, r, paint);
        }
    }
}
Beispiel #24
0
void* sk_malloc_throw(size_t size)
{
	return sk_malloc_flags(size, 2);
}
void* sk_malloc_throw(size_t size) {
    return sk_malloc_flags(size, SK_MALLOC_THROW);
}
    static void* pdf_alloc_nl(FPDFEMB_MEMMGR* pMgr, unsigned int size) {
        void* addr = sk_malloc_flags(size, 0);
 //       SkDebugf("---- pdf_alloc_nl %d %p\n", size, addr);
        return addr;
    }