// Return the context associated with the next logical typeface, or NULL if
// there are no more entries in the fallback chain.
SkScalerContext* SkScalerContext::allocNextContext() const {
#ifdef SK_BUILD_FOR_ANDROID
    SkTypeface* newFace = SkAndroidNextLogicalTypeface(fRec.fFontID,
                                                       fRec.fOrigFontID,
                                                       fPaintOptionsAndroid);
    if (0 == newFace) {
        return NULL;
    }

    SkAutoTUnref<SkTypeface> aur(newFace);
    uint32_t newFontID = newFace->uniqueID();

    SkWriteBuffer androidBuffer;
    fPaintOptionsAndroid.flatten(androidBuffer);

    SkAutoDescriptor    ad(sizeof(fRec) + androidBuffer.bytesWritten()
                           + SkDescriptor::ComputeOverhead(2));
    SkDescriptor*       desc = ad.getDesc();

    desc->init();
    SkScalerContext::Rec* newRec =
    (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag,
                                          sizeof(fRec), &fRec);
    androidBuffer.writeToMemory(desc->addEntry(kAndroidOpts_SkDescriptorTag,
                                               androidBuffer.bytesWritten(), NULL));

    newRec->fFontID = newFontID;
    desc->computeChecksum();

    return newFace->createScalerContext(desc);
#else
    return NULL;
#endif
}
Esempio n. 2
0
void SkGPipeCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
                                   const SkPaint& paint) {
    NOTIFY_SETUP(this);
    this->writePaint(paint);

    // FIXME: this is inefficient but avoids duplicating the blob serialization logic.
    SkRefCntSet typefaceSet;
    SkWriteBuffer blobBuffer;
    blobBuffer.setTypefaceRecorder(&typefaceSet);
    blob->flatten(blobBuffer);

    // Unlike most draw ops (which only use one paint/typeface), text blobs may reference
    // an arbitrary number of typefaces. Since the one-paint-per-op model is not applicable,
    // we need to serialize these explicitly.
    TypefaceBuffer typefaceBuffer;
    size_t typefaceSize = is_cross_process(fFlags)
        ? this->getCrossProcessTypefaces(typefaceSet, &typefaceBuffer)
        : this->getInProcessTypefaces(typefaceSet, &typefaceBuffer);

    // blob byte count + typeface count + x + y + blob data + an index (cross-process)
    // or pointer (in-process) for each typeface
    size_t size = 2 * sizeof(uint32_t)
                + 2 * sizeof(SkScalar)
                + blobBuffer.bytesWritten()
                + typefaceSize;

    if (this->needOpBytes(size)) {
        this->writeOp(kDrawTextBlob_DrawOp);
        SkDEBUGCODE(size_t initialOffset = fWriter.bytesWritten();)
SkData* SkValidatingSerializeFlattenable(SkFlattenable* flattenable) {
    SkWriteBuffer writer;
    writer.writeFlattenable(flattenable);
    size_t size = writer.bytesWritten();
    auto data = SkData::MakeUninitialized(size);
    writer.writeToMemory(data->writable_data());
    return data.release();
}
Esempio n. 4
0
static void flatten(const SkFlattenable* flattenable, Json::Value* target, bool sendBinaries) {
    if (sendBinaries) {
        SkWriteBuffer buffer;
        flattenable->flatten(buffer);
        void* data = sk_malloc_throw(buffer.bytesWritten());
        buffer.writeToMemory(data);
        Json::Value bytes;
        encode_data(data, buffer.bytesWritten(), &bytes);
        Json::Value jsonFlattenable;
        jsonFlattenable[SKJSONCANVAS_ATTRIBUTE_NAME] = Json::Value(flattenable->getTypeName());
        jsonFlattenable[SKJSONCANVAS_ATTRIBUTE_BYTES] = bytes;
        (*target) = jsonFlattenable;
        free(data);
    }
    else {
        (*target)[SKJSONCANVAS_ATTRIBUTE_DESCRIPTION] = Json::Value(flattenable->getTypeName());
    }
}
Esempio n. 5
0
static sk_sp<SkColorFilter> reincarnate_colorfilter(SkFlattenable* obj) {
    SkWriteBuffer wb;
    wb.writeFlattenable(obj);

    size_t size = wb.bytesWritten();
    SkAutoSMalloc<1024> storage(size);
    // make a copy into storage
    wb.writeToMemory(storage.get());

    SkReadBuffer rb(storage.get(), size);
    return rb.readColorFilter();
}
Esempio n. 6
0
DEF_TEST(DashPathEffectTest_crbug_348821, r) {
    SkScalar intervals[] = { 1.76934361e+36f, 2.80259693e-45f };  // Values from bug.
    const int count = 2;
    SkScalar phase = SK_ScalarInfinity;  // Used to force the bad fInitialDashLength = -1 path.
    SkAutoTUnref<SkDashPathEffect> dash(SkDashPathEffect::Create(intervals, count, phase));

    // nullptr -> refuses to work with flattening framework.
    REPORTER_ASSERT(r, dash->getFactory() != nullptr);

    SkWriteBuffer buffer;
    buffer.writeFlattenable(dash);
    REPORTER_ASSERT(r, buffer.bytesWritten() > 12);  // We'd write 12 if broken, >=40 if not.
}
Esempio n. 7
0
bool SkGPipeCanvas::shuttleBitmap(const SkBitmap& bm, int32_t slot) {
    SkASSERT(shouldFlattenBitmaps(fFlags));
    SkWriteBuffer buffer;
    buffer.setNamedFactoryRecorder(fFactorySet);
    buffer.writeBitmap(bm);
    this->flattenFactoryNames();
    size_t size = buffer.bytesWritten();
    if (this->needOpBytes(size)) {
        this->writeOp(kDef_Bitmap_DrawOp, 0, slot);
        void* dst = static_cast<void*>(fWriter.reserve(size));
        buffer.writeToMemory(dst);
        return true;
    }
    return false;
}
Esempio n. 8
0
DEF_TEST(Paint_flattening, reporter) {
    const SkFilterQuality levels[] = {
        kNone_SkFilterQuality,
        kLow_SkFilterQuality,
        kMedium_SkFilterQuality,
        kHigh_SkFilterQuality,
    };
    const SkPaint::Hinting hinting[] = {
        SkPaint::kNo_Hinting,
        SkPaint::kSlight_Hinting,
        SkPaint::kNormal_Hinting,
        SkPaint::kFull_Hinting,
    };
    const SkPaint::Align align[] = {
        SkPaint::kLeft_Align,
        SkPaint::kCenter_Align,
        SkPaint::kRight_Align
    };
    const SkPaint::Cap caps[] = {
        SkPaint::kButt_Cap,
        SkPaint::kRound_Cap,
        SkPaint::kSquare_Cap,
    };
    const SkPaint::Join joins[] = {
        SkPaint::kMiter_Join,
        SkPaint::kRound_Join,
        SkPaint::kBevel_Join,
    };
    const SkPaint::TextEncoding encodings[] = {
        SkPaint::kUTF8_TextEncoding,
        SkPaint::kUTF16_TextEncoding,
        SkPaint::kUTF32_TextEncoding,
        SkPaint::kGlyphID_TextEncoding,
    };
    const SkPaint::Style styles[] = {
        SkPaint::kFill_Style,
        SkPaint::kStroke_Style,
        SkPaint::kStrokeAndFill_Style,
    };

#define FOR_SETUP(index, array, setter)                                 \
    for (size_t index = 0; index < SK_ARRAY_COUNT(array); ++index) {    \
        paint.setter(array[index]);                                     \

    SkPaint paint;
    paint.setFlags(0x1234);

    FOR_SETUP(i, levels, setFilterQuality)
    FOR_SETUP(j, hinting, setHinting)
    FOR_SETUP(k, align, setTextAlign)
    FOR_SETUP(l, caps, setStrokeCap)
    FOR_SETUP(m, joins, setStrokeJoin)
    FOR_SETUP(n, encodings, setTextEncoding)
    FOR_SETUP(p, styles, setStyle)

    SkWriteBuffer writer;
    paint.flatten(writer);

    const uint32_t* written = writer.getWriter32()->contiguousArray();
    SkReadBuffer reader(written, writer.bytesWritten());

    SkPaint paint2;
    paint2.unflatten(reader);
    REPORTER_ASSERT(reporter, paint2 == paint);

    }}}}}}}