Example #1
0
void SkSVGDevice::AutoElement::addTextAttributes(const SkPaint& paint) {
    this->addAttribute("font-size", paint.getTextSize());

    if (const char* textAlign = svg_text_align(paint.getTextAlign())) {
        this->addAttribute("text-anchor", textAlign);
    }

    SkString familyName;
    SkTHashSet<SkString> familySet;
    SkAutoTUnref<const SkTypeface> tface(paint.getTypeface() ?
        SkRef(paint.getTypeface()) : SkTypeface::RefDefault());

    SkASSERT(tface);
    SkTypeface::Style style = tface->style();
    if (style & SkTypeface::kItalic) {
        this->addAttribute("font-style", "italic");
    }
    if (style & SkTypeface::kBold) {
        this->addAttribute("font-weight", "bold");
    }

    SkAutoTUnref<SkTypeface::LocalizedStrings> familyNameIter(tface->createFamilyNameIterator());
    SkTypeface::LocalizedString familyString;
    while (familyNameIter->next(&familyString)) {
        if (familySet.contains(familyString.fString)) {
            continue;
        }
        familySet.add(familyString.fString);
        familyName.appendf((familyName.isEmpty() ? "%s" : ", %s"), familyString.fString.c_str());
    }

    if (!familyName.isEmpty()) {
        this->addAttribute("font-family", familyName);
    }
}
Example #2
0
static void drawKernText(SkCanvas* canvas, const void* text, size_t len,
                         SkScalar x, SkScalar y, const SkPaint& paint) {
    SkTypeface* face = paint.getTypeface();
    if (!face) {
        canvas->drawText(text, len, x, y, paint);
        return;
    }

    SkAutoSTMalloc<128, uint16_t> glyphStorage(len);
    uint16_t* glyphs = glyphStorage.get();
    int glyphCount = paint.textToGlyphs(text, len, glyphs);
    if (glyphCount < 1) {
        return;
    }

    SkAutoSTMalloc<128, int32_t> adjustmentStorage(glyphCount - 1);
    int32_t* adjustments = adjustmentStorage.get();
    if (!face->getKerningPairAdjustments(glyphs, glyphCount, adjustments)) {
        canvas->drawText(text, len, x, y, paint);
        return;
    }

    SkPaint glyphPaint(paint);
    glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);

    SkAutoSTMalloc<128, SkPoint> posStorage(glyphCount);
    SkPoint* pos = posStorage.get();
    getGlyphPositions(glyphPaint, glyphs, glyphCount, x, y, pos);

    applyKerning(pos, adjustments, glyphCount, glyphPaint);
    canvas->drawPosText(glyphs, glyphCount * sizeof(uint16_t), pos, glyphPaint);
}
Example #3
0
sk_sp<SkFont> SkFont::Testing_CreateFromPaint(const SkPaint& paint) {
    uint32_t flags = 0;
    if (paint.isVerticalText()) {
        flags |= kVertical_Flag;
    }
    if (paint.isEmbeddedBitmapText()) {
        flags |= kEmbeddedBitmaps_Flag;
    }
    if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
        flags |= kGenA8FromLCD_Flag;
    }
    if (paint.isFakeBoldText()) {
        flags |= kEmbolden_Flag;
    }

    if (SkPaint::kFull_Hinting == paint.getHinting()) {
        flags |= kEnableByteCodeHints_Flag;
    }
    if (paint.isAutohinted()) {
        flags |= kEnableAutoHints_Flag;
    }
    if (paint.isSubpixelText() || paint.isLinearText()) {
        // this is our default
    } else {
        flags |= kUseNonlinearMetrics_Flag;
    }

    MaskType maskType = SkFont::kBW_MaskType;
    if (paint.isAntiAlias()) {
        maskType = paint.isLCDRenderText() ? kLCD_MaskType : kA8_MaskType;
    }

    return Make(sk_ref_sp(paint.getTypeface()), paint.getTextSize(), paint.getTextScaleX(),
                paint.getTextSkewX(), maskType, flags);
}
Example #4
0
static void test_cachedfont(skiatest::Reporter* reporter, const SkPaint& paint) {
    SkAutoTUnref<SkFont> font(SkFont::Testing_CreateFromPaint(paint));

    // Currently SkFont resolves null into the default, so only test if paint's is not null
    if (paint.getTypeface()) {
        REPORTER_ASSERT(reporter, font->getTypeface() == paint.getTypeface());
    }
    REPORTER_ASSERT(reporter, font->getSize() == paint.getTextSize());
    REPORTER_ASSERT(reporter, font->getScaleX() == paint.getTextScaleX());
    REPORTER_ASSERT(reporter, font->getSkewX() == paint.getTextSkewX());

    REPORTER_ASSERT(reporter, font->isVertical() == paint.isVerticalText());
    REPORTER_ASSERT(reporter, font->isEmbolden() == paint.isFakeBoldText());

    REPORTER_ASSERT(reporter, font->isUseNonLinearMetrics() == is_use_nonlinear_metrics(paint));
    REPORTER_ASSERT(reporter, font->isEnableAutoHints() == is_enable_auto_hints(paint));
    REPORTER_ASSERT(reporter, font->isEnableByteCodeHints() == is_enable_bytecode_hints(paint));
}
Example #5
0
static void charsToGlyphsNull_proc(int loops, const SkPaint& paint, const void* text,
                                   size_t len, int glyphCount) {
    SkTypeface::Encoding encoding = paint2Encoding(paint);

    SkTypeface* face = paint.getTypeface();
    for (int i = 0; i < loops; ++i) {
        face->charsToGlyphs(text, encoding, NULL, glyphCount);
    }
}
Example #6
0
static void applyKerning(SkPoint pos[], const int32_t adjustments[], int count,
                         const SkPaint& paint) {
    SkScalar scale = paint.getTextSize() / paint.getTypeface()->getUnitsPerEm();

    SkScalar globalAdj = 0;
    for (int i = 0; i < count - 1; ++i) {
        globalAdj += adjustments[i] * scale;
        pos[i + 1].fX += globalAdj;
    }
}
Example #7
0
DEF_TEST(Paint_cmap, reporter) {
    // need to implement charsToGlyphs on other backends (e.g. linux, win)
    // before we can run this tests everywhere
    return;

    static const int NGLYPHS = 64;

    SkUnichar src[NGLYPHS];
    SkUnichar dst[NGLYPHS]; // used for utf8, utf16, utf32 storage

    static const struct {
        size_t (*fSeedTextProc)(const SkUnichar[], void* dst, int count);
        SkPaint::TextEncoding   fEncoding;
    } gRec[] = {
        { uni_to_utf8,  SkPaint::kUTF8_TextEncoding },
        { uni_to_utf16, SkPaint::kUTF16_TextEncoding },
        { uni_to_utf32, SkPaint::kUTF32_TextEncoding },
    };

    SkRandom rand;
    SkPaint paint;
    paint.setTypeface(SkTypeface::RefDefault())->unref();
    SkTypeface* face = paint.getTypeface();

    for (int i = 0; i < 1000; ++i) {
        // generate some random text
        for (int j = 0; j < NGLYPHS; ++j) {
            src[j] = ' ' + j;
        }
        // inject some random chars, to sometimes abort early
        src[rand.nextU() & 63] = rand.nextU() & 0xFFF;

        for (size_t k = 0; k < SK_ARRAY_COUNT(gRec); ++k) {
            paint.setTextEncoding(gRec[k].fEncoding);

            size_t len = gRec[k].fSeedTextProc(src, dst, NGLYPHS);

            uint16_t    glyphs0[NGLYPHS], glyphs1[NGLYPHS];

            bool contains = paint.containsText(dst, len);
            int nglyphs = paint.textToGlyphs(dst, len, glyphs0);
            int first = face->charsToGlyphs(dst, paint2encoding(paint), glyphs1, NGLYPHS);
            int index = find_first_zero(glyphs1, NGLYPHS);

            REPORTER_ASSERT(reporter, NGLYPHS == nglyphs);
            REPORTER_ASSERT(reporter, index == first);
            REPORTER_ASSERT(reporter, 0 == memcmp(glyphs0, glyphs1, NGLYPHS * sizeof(uint16_t)));
            if (contains) {
                REPORTER_ASSERT(reporter, NGLYPHS == first);
            } else {
                REPORTER_ASSERT(reporter, NGLYPHS > first);
            }
        }
    }
}
Example #8
0
static void charsToGlyphs_proc(int loops, const SkPaint& paint, const void* text,
                               size_t len, int glyphCount) {
    SkTypeface::Encoding encoding = paint2Encoding(paint);
    uint16_t glyphs[NGLYPHS];
    SkASSERT(glyphCount <= NGLYPHS);

    SkTypeface* face = paint.getTypeface();
    for (int i = 0; i < loops; ++i) {
        face->charsToGlyphs(text, encoding, glyphs, glyphCount);
    }
}
Example #9
0
DEF_TEST(FontHostStream, reporter) {
    {
        SkPaint paint;
        paint.setColor(SK_ColorGRAY);
        paint.setTextSize(SkIntToScalar(30));

        SkTypeface* fTypeface = SkTypeface::CreateFromName("Georgia",
                                                           SkTypeface::kNormal);
        SkSafeUnref(paint.setTypeface(fTypeface));

        SkIRect origRect = SkIRect::MakeWH(64, 64);
        SkBitmap origBitmap;
        create(&origBitmap, origRect);
        SkCanvas origCanvas(origBitmap);

        SkIRect streamRect = SkIRect::MakeWH(64, 64);
        SkBitmap streamBitmap;
        create(&streamBitmap, streamRect);
        SkCanvas streamCanvas(streamBitmap);

        SkPoint point = SkPoint::Make(24, 32);

        // Test: origTypeface and streamTypeface from orig data draw the same
        drawBG(&origCanvas);
        origCanvas.drawText("A", 1, point.fX, point.fY, paint);

        SkTypeface* origTypeface = paint.getTypeface();
        SkAutoTUnref<SkTypeface> aur;
        if (NULL == origTypeface) {
            origTypeface = aur.reset(SkTypeface::RefDefault());
        }

        int ttcIndex;
        SkAutoTDelete<SkStreamAsset> fontData(origTypeface->openStream(&ttcIndex));
        SkTypeface* streamTypeface = SkTypeface::CreateFromStream(fontData.detach());

        SkFontDescriptor desc;
        bool isLocalStream = false;
        streamTypeface->getFontDescriptor(&desc, &isLocalStream);
        REPORTER_ASSERT(reporter, isLocalStream);

        SkSafeUnref(paint.setTypeface(streamTypeface));
        drawBG(&streamCanvas);
        streamCanvas.drawPosText("A", 1, &point, paint);

        REPORTER_ASSERT(reporter,
                        compare(origBitmap, origRect, streamBitmap, streamRect));
    }
    //Make sure the typeface is deleted and removed.
    SkGraphics::PurgeFontCache();
}
Example #10
0
static uint16_t compute_nondef(const SkPaint& paint, PaintUsage usage) {
    // kRespectsStroke_PaintUsage is only valid if other bits are also set
    SkASSERT(0 != (usage & ~kRespectsStroke_PaintUsage));

    const SkScalar kTextSize_Default    = 12;
    const SkScalar kTextScaleX_Default  = 1;
    const SkScalar kTextSkewX_Default   = 0;
    const SkScalar kStrokeWidth_Default = 0;
    const SkScalar kStrokeMiter_Default = 4;
    const SkColor  kColor_Default       = SK_ColorBLACK;

    unsigned bits = (paint.getColor() != kColor_Default) ? kColor_NonDef : 0;

    if (usage & kText_PaintUsage) {
        bits |= (paint.getTextSize() != kTextSize_Default       ? kTextSize_NonDef : 0);
        bits |= (paint.getTextScaleX() != kTextScaleX_Default   ? kTextScaleX_NonDef : 0);
        bits |= (paint.getTextSkewX() != kTextSkewX_Default     ? kTextSkewX_NonDef : 0);
        bits |= (paint.getTypeface()                            ? kTypeface_NonDef : 0);
    }

    // TODO: kImage_PaintUsage only needs the shader/maskfilter IF its colortype is kAlpha_8

    if (usage & (kVertices_PaintUsage | kDrawPaint_PaintUsage | kImage_PaintUsage |
                 kText_PaintUsage | kGeometry_PaintUsage | kTextBlob_PaintUsage)) {
        bits |= (paint.getShader()      ? kShader_NonDef : 0);
    }

    if (usage & (kText_PaintUsage | kGeometry_PaintUsage | kTextBlob_PaintUsage)) {
        bits |= (paint.getPathEffect()  ? kPathEffect_NonDef : 0);
        bits |= (paint.getRasterizer()  ? kRasterizer_NonDef : 0);

        if (paint.getStyle() != SkPaint::kFill_Style || (usage & kRespectsStroke_PaintUsage)) {
            bits |= (paint.getStrokeWidth() != kStrokeWidth_Default ? kStrokeWidth_NonDef : 0);
            bits |= (paint.getStrokeMiter() != kStrokeMiter_Default ? kStrokeMiter_NonDef : 0);
        }
    }

    if (usage &
        (kText_PaintUsage | kGeometry_PaintUsage | kImage_PaintUsage | kTextBlob_PaintUsage))
    {
        bits |= (paint.getMaskFilter()  ? kMaskFilter_NonDef : 0);
    }

    bits |= (paint.getColorFilter() ? kColorFilter_NonDef : 0);
    bits |= (paint.getImageFilter() ? kImageFilter_NonDef : 0);
    bits |= (paint.getDrawLooper()  ? kDrawLooper_NonDef : 0);

    return SkToU16(bits);
}
Example #11
0
void SkPDFDevice::updateFont(const SkPaint& paint, uint16_t glyphID) {
    SkTypeface* typeface = paint.getTypeface();
    if (fGraphicStack[fGraphicStackIndex].fTextSize != paint.getTextSize() ||
            fGraphicStack[fGraphicStackIndex].fFont == NULL ||
            fGraphicStack[fGraphicStackIndex].fFont->typeface() != typeface ||
            !fGraphicStack[fGraphicStackIndex].fFont->hasGlyph(glyphID)) {
        int fontIndex = getFontResourceIndex(typeface, glyphID);
        fContent.writeText("/F");
        fContent.writeDecAsText(fontIndex);
        fContent.writeText(" ");
        SkPDFScalar::Append(paint.getTextSize(), &fContent);
        fContent.writeText(" Tf\n");
        fGraphicStack[fGraphicStackIndex].fTextSize = paint.getTextSize();
        fGraphicStack[fGraphicStackIndex].fFont = fFontResources[fontIndex];
    }
}
Example #12
0
static void apply_paint_typeface(const SkPaint& paint, Json::Value* target, 
                                 bool sendBinaries) {
    SkTypeface* typeface = paint.getTypeface();
    if (typeface != nullptr) {
        if (sendBinaries) {
            Json::Value jsonTypeface;
            SkDynamicMemoryWStream buffer;
            typeface->serialize(&buffer);
            void* data = sk_malloc_throw(buffer.bytesWritten());
            buffer.copyTo(data);
            Json::Value bytes;
            encode_data(data, buffer.bytesWritten(), &bytes);
            jsonTypeface[SKJSONCANVAS_ATTRIBUTE_BYTES] = bytes;
            free(data);
            (*target)[SKJSONCANVAS_ATTRIBUTE_TYPEFACE] = jsonTypeface;
        }
    }
}
Example #13
0
GlyphSet::GlyphSet(const SkPaint& paint, const UChar* lower, const UChar* upper,
            size_t byteLength) {
    SkPaint clonePaint(paint);
    clonePaint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
    mTypeface = paint.getTypeface();
    mCount = clonePaint.textToGlyphs(lower, byteLength, NULL);
    if (mCount > MAX_STORAGE_COUNT) {
        mLowerGlyphs = new uint16_t[2*mCount];
    } else {
        mLowerGlyphs = &mStorage[0];
    }
    // Use one array, and have mUpperGlyphs point to a portion of it,
    // so that we can reduce the number of new/deletes
    mUpperGlyphs = mLowerGlyphs + mCount;
    int count2 = clonePaint.textToGlyphs(lower, byteLength, mLowerGlyphs);
    SkASSERT(mCount == count2);
    count2 = clonePaint.textToGlyphs(upper, byteLength, mUpperGlyphs);
    SkASSERT(mCount == count2);
}
Example #14
0
static void cgSetPaintForText(CGContextRef cg, const SkPaint& paint) {
    SkColor c = paint.getColor();
    CGFloat rgba[] = {
        SkColorGetB(c) / 255.0f,
        SkColorGetG(c) / 255.0f,
        SkColorGetR(c) / 255.0f,
        SkColorGetA(c) / 255.0f,
    };
    CGContextSetRGBFillColor(cg, rgba[0], rgba[1], rgba[2], rgba[3]);

    CGContextSetTextDrawingMode(cg, kCGTextFill);
    CGContextSetFont(cg, typefaceToCGFont(paint.getTypeface()));
    CGContextSetFontSize(cg, SkScalarToFloat(paint.getTextSize()));

    CGContextSetAllowsFontSubpixelPositioning(cg, paint.isSubpixelText());
    CGContextSetShouldSubpixelPositionFonts(cg, paint.isSubpixelText());

    CGContextSetShouldAntialias(cg, paint.isAntiAlias());
    CGContextSetShouldSmoothFonts(cg, paint.isLCDRenderText());
}
Example #15
0
    void onDraw(SkCanvas* canvas) override {
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setSubpixelText(true);
        paint.setTextSize(100);
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setTextScaleX(fScaleX);
        paint.setTextSkewX(fSkewX);

        const SkColor boundsColors[2] = { SK_ColorRED, SK_ColorBLUE };

        SkFontMgr* fm = fFM;
        int count = SkMin32(fm->countFamilies(), 32);

        int index = 0;
        SkScalar x = 0, y = 0;

        canvas->translate(80, 120);

        for (int i = 0; i < count; ++i) {
            SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i));
            for (int j = 0; j < set->count(); ++j) {
                SkSafeUnref(paint.setTypeface(set->createTypeface(j)));
                if (paint.getTypeface()) {
                    show_bounds(canvas, paint, x, y, boundsColors[index & 1]);
                    index += 1;
                    x += 160;
                    if (0 == (index % 6)) {
                        x = 0;
                        y += 160;
                    }
                    if (index >= 30) {
                        return;
                    }
                }
            }
        }
    }
Example #16
0
/*
 *  Header:
 *      paint flags     : 32
 *      non_def bits    : 16
 *      xfermode enum   : 8
 *      pad zeros       : 8
 */
static void write_paint(SkWriteBuffer& writer, const SkPaint& paint, unsigned usage) {
    uint32_t packedFlags = pack_paint_flags(paint.getFlags(), paint.getHinting(),
                                            paint.getTextAlign(), paint.getFilterQuality(),
                                            paint.getStyle(), paint.getStrokeCap(),
                                            paint.getStrokeJoin(), paint.getTextEncoding());
    writer.write32(packedFlags);

    unsigned nondef = compute_nondef(paint, (PaintUsage)usage);
    const uint8_t pad = 0;
    writer.write32((nondef << 16) | ((unsigned)paint.getBlendMode() << 8) | pad);

    CHECK_WRITE_SCALAR(writer, nondef, paint, TextSize);
    CHECK_WRITE_SCALAR(writer, nondef, paint, TextScaleX);
    CHECK_WRITE_SCALAR(writer, nondef, paint, TextSkewX);
    CHECK_WRITE_SCALAR(writer, nondef, paint, StrokeWidth);
    CHECK_WRITE_SCALAR(writer, nondef, paint, StrokeMiter);

    if (nondef & kColor_NonDef) {
        writer.write32(paint.getColor());
    }
    if (nondef & kTypeface_NonDef) {
        // TODO: explore idea of writing bits indicating "use the prev (or prev N) face"
        // e.g. 1-N bits is an index into a ring buffer of typefaces
        SkTypeface* tf = paint.getTypeface();
        SkASSERT(tf);
        writer.writeTypeface(tf);
    }

    CHECK_WRITE_FLATTENABLE(writer, nondef, paint, PathEffect);
    CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Shader);
    CHECK_WRITE_FLATTENABLE(writer, nondef, paint, MaskFilter);
    CHECK_WRITE_FLATTENABLE(writer, nondef, paint, ColorFilter);
    CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Rasterizer);
    CHECK_WRITE_FLATTENABLE(writer, nondef, paint, ImageFilter);
    CHECK_WRITE_FLATTENABLE(writer, nondef, paint, DrawLooper);
}
Example #17
0
void SimpleFontData::platformInit()
{
    if (!m_platformData.size()) {
        m_fontMetrics.reset();
        m_avgCharWidth = 0;
        m_maxCharWidth = 0;
        return;
    }

    SkPaint paint;
    SkPaint::FontMetrics metrics;

    m_platformData.setupPaint(&paint);
    paint.getFontMetrics(&metrics);
    const SkFontID fontID = m_platformData.uniqueID();

    static const uint32_t vdmxTag = SkSetFourByteTag('V', 'D', 'M', 'X');
    int pixelSize = m_platformData.size() + 0.5;
    int vdmxAscent, vdmxDescent;
    bool isVDMXValid = false;

    size_t vdmxSize = SkFontHost::GetTableSize(fontID, vdmxTag);
    if (vdmxSize && vdmxSize < maxVDMXTableSize) {
        uint8_t* vdmxTable = (uint8_t*) fastMalloc(vdmxSize);
        if (vdmxTable
            && SkFontHost::GetTableData(fontID, vdmxTag, 0, vdmxSize, vdmxTable) == vdmxSize
            && parseVDMX(&vdmxAscent, &vdmxDescent, vdmxTable, vdmxSize, pixelSize))
            isVDMXValid = true;
        fastFree(vdmxTable);
    }

    float ascent;
    float descent;

    // Beware those who step here: This code is designed to match Win32 font
    // metrics *exactly* (except the adjustment of ascent/descent on Linux/Android).
    if (isVDMXValid) {
        ascent = vdmxAscent;
        descent = -vdmxDescent;
    } else {
        SkScalar height = -metrics.fAscent + metrics.fDescent + metrics.fLeading;
        ascent = SkScalarRound(-metrics.fAscent);
        descent = SkScalarRound(height) - ascent;
#if OS(LINUX) || OS(ANDROID)
        // When subpixel positioning is enabled, if the descent is rounded down, the descent part
        // of the glyph may be truncated when displayed in a 'overflow: hidden' container.
        // To avoid that, borrow 1 unit from the ascent when possible.
        // FIXME: This can be removed if sub-pixel ascent/descent is supported.
        if (platformData().fontRenderStyle().useSubpixelPositioning && descent < SkScalarToFloat(metrics.fDescent) && ascent >= 1) {
            ++descent;
            --ascent;
        }
#endif
    }

    m_fontMetrics.setAscent(ascent);
    m_fontMetrics.setDescent(descent);

    float xHeight;
    if (metrics.fXHeight) {
        xHeight = metrics.fXHeight;
        m_fontMetrics.setXHeight(xHeight);
    } else {
        xHeight = ascent * 0.56; // Best guess from Windows font metrics.
        m_fontMetrics.setXHeight(xHeight);
        m_fontMetrics.setHasXHeight(false);
    }


    float lineGap = SkScalarToFloat(metrics.fLeading);
    m_fontMetrics.setLineGap(lineGap);
    m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));

    if (platformData().orientation() == Vertical && !isTextOrientationFallback()) {
        static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a');
        static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G');
        size_t vheaSize = SkFontHost::GetTableSize(fontID, vheaTag);
        size_t vorgSize = SkFontHost::GetTableSize(fontID, vorgTag);
        if ((vheaSize > 0) || (vorgSize > 0))
            m_hasVerticalGlyphs = true;
    }

    // In WebKit/WebCore/platform/graphics/SimpleFontData.cpp, m_spaceWidth is
    // calculated for us, but we need to calculate m_maxCharWidth and
    // m_avgCharWidth in order for text entry widgets to be sized correctly.

    SkScalar xRange = metrics.fXMax - metrics.fXMin;
    m_maxCharWidth = SkScalarRound(xRange * SkScalarRound(m_platformData.size()));

    if (metrics.fAvgCharWidth)
        m_avgCharWidth = SkScalarRound(metrics.fAvgCharWidth);
    else {
        m_avgCharWidth = xHeight;

        GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();

        if (glyphPageZero) {
            static const UChar32 xChar = 'x';
            const Glyph xGlyph = glyphPageZero->glyphDataForCharacter(xChar).glyph;

            if (xGlyph) {
                // In widthForGlyph(), xGlyph will be compared with
                // m_zeroWidthSpaceGlyph, which isn't initialized yet here.
                // Initialize it with zero to make sure widthForGlyph() returns
                // the right width.
                m_zeroWidthSpaceGlyph = 0;
                m_avgCharWidth = widthForGlyph(xGlyph);
            }
        }
    }

    if (int unitsPerEm = paint.getTypeface()->getUnitsPerEm())
        m_fontMetrics.setUnitsPerEm(unitsPerEm);
}
Example #18
0
void SimpleFontData::platformInit() {
  if (!m_platformData.size()) {
    m_fontMetrics.reset();
    m_avgCharWidth = 0;
    m_maxCharWidth = 0;
    return;
  }

  SkPaint paint;
  SkPaint::FontMetrics metrics;

  m_platformData.setupPaint(&paint);
  paint.getFontMetrics(&metrics);
  SkTypeface* face = paint.getTypeface();
  ASSERT(face);

  int vdmxAscent = 0, vdmxDescent = 0;
  bool isVDMXValid = false;

#if OS(LINUX) || OS(ANDROID)
  // Manually digging up VDMX metrics is only applicable when bytecode hinting
  // using FreeType. With GDI, the metrics will already have taken this into
  // account (as needed). With DirectWrite or CoreText, no bytecode hinting is
  // ever done. This code should be pushed into FreeType (hinted font metrics).
  static const uint32_t vdmxTag = SkSetFourByteTag('V', 'D', 'M', 'X');
  int pixelSize = m_platformData.size() + 0.5;
  if (!paint.isAutohinted() &&
      (paint.getHinting() == SkPaint::kFull_Hinting ||
       paint.getHinting() == SkPaint::kNormal_Hinting)) {
    size_t vdmxSize = face->getTableSize(vdmxTag);
    if (vdmxSize && vdmxSize < maxVDMXTableSize) {
      uint8_t* vdmxTable = (uint8_t*)fastMalloc(vdmxSize);
      if (vdmxTable &&
          face->getTableData(vdmxTag, 0, vdmxSize, vdmxTable) == vdmxSize &&
          parseVDMX(&vdmxAscent, &vdmxDescent, vdmxTable, vdmxSize, pixelSize))
        isVDMXValid = true;
      fastFree(vdmxTable);
    }
  }
#endif

  float ascent;
  float descent;

  // Beware those who step here: This code is designed to match Win32 font
  // metrics *exactly* (except the adjustment of ascent/descent on
  // Linux/Android).
  if (isVDMXValid) {
    ascent = vdmxAscent;
    descent = -vdmxDescent;
  } else {
    ascent = SkScalarRoundToInt(-metrics.fAscent);
    descent = SkScalarRoundToInt(metrics.fDescent);
#if OS(LINUX) || OS(ANDROID)
    // When subpixel positioning is enabled, if the descent is rounded down, the
    // descent part of the glyph may be truncated when displayed in a 'overflow:
    // hidden' container. To avoid that, borrow 1 unit from the ascent when
    // possible.
    // FIXME: This can be removed if sub-pixel ascent/descent is supported.
    if (platformData().fontRenderStyle().useSubpixelPositioning &&
        descent < SkScalarToFloat(metrics.fDescent) && ascent >= 1) {
      ++descent;
      --ascent;
    }
#endif
  }

  m_fontMetrics.setAscent(ascent);
  m_fontMetrics.setDescent(descent);

  float xHeight;
  if (metrics.fXHeight) {
    xHeight = metrics.fXHeight;
    m_fontMetrics.setXHeight(xHeight);
  } else {
    xHeight = ascent * 0.56;  // Best guess from Windows font metrics.
    m_fontMetrics.setXHeight(xHeight);
    m_fontMetrics.setHasXHeight(false);
  }

  float lineGap = SkScalarToFloat(metrics.fLeading);
  m_fontMetrics.setLineGap(lineGap);
  m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) +
                               lroundf(lineGap));

  SkScalar underlineThickness, underlinePosition;
  if (metrics.hasUnderlineThickness(&underlineThickness) &&
      metrics.hasUnderlinePosition(&underlinePosition)) {
    m_fontMetrics.setUnderlineThickness(SkScalarToFloat(underlineThickness));
    m_fontMetrics.setUnderlinePosition(SkScalarToFloat(-underlinePosition));
  }

  if (platformData().orientation() == Vertical &&
      !isTextOrientationFallback()) {
    static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a');
    static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G');
    size_t vheaSize = face->getTableSize(vheaTag);
    size_t vorgSize = face->getTableSize(vorgTag);
    if ((vheaSize > 0) || (vorgSize > 0))
      m_hasVerticalGlyphs = true;
  }

  // In WebKit/WebCore/platform/graphics/SimpleFontData.cpp, m_spaceWidth is
  // calculated for us, but we need to calculate m_maxCharWidth and
  // m_avgCharWidth in order for text entry widgets to be sized correctly.
  // FIXME: This seems incorrect and should probably use fMaxCharWidth as
  // the code path above.
  SkScalar xRange = metrics.fXMax - metrics.fXMin;
  m_maxCharWidth =
      SkScalarRoundToInt(xRange * SkScalarRoundToInt(m_platformData.size()));

  if (metrics.fAvgCharWidth)
    m_avgCharWidth = SkScalarRoundToInt(metrics.fAvgCharWidth);
  else {
    m_avgCharWidth = xHeight;

    GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();

    if (glyphPageZero) {
      static const UChar32 xChar = 'x';
      const Glyph xGlyph = glyphPageZero->glyphForCharacter(xChar);

      if (xGlyph) {
        // In widthForGlyph(), xGlyph will be compared with
        // m_zeroWidthSpaceGlyph, which isn't initialized yet here.
        // Initialize it with zero to make sure widthForGlyph() returns
        // the right width.
        m_zeroWidthSpaceGlyph = 0;
        m_avgCharWidth = widthForGlyph(xGlyph);
      }
    }
  }

  if (int unitsPerEm = face->getUnitsPerEm())
    m_fontMetrics.setUnitsPerEm(unitsPerEm);
}
// Even with kEntirePaint_Bits, we always ensure that the master paint's
// text-encoding is respected, since that controls how we interpret the
// text/length parameters of a draw[Pos]Text call.
void SkLayerDrawLooper::LayerDrawLooperContext::ApplyInfo(
        SkPaint* dst, const SkPaint& src, const LayerInfo& info) {
    SkColor4f srcColor = src.getColor4f();
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    // The framework may respect the alpha value on the original paint.
    // Match this legacy behavior.
    if (src.getAlpha() == 255) {
        srcColor.fA = dst->getColor4f().fA;
    }
#endif
    dst->setColor4f(xferColor(srcColor, dst->getColor4f(), (SkBlendMode)info.fColorMode),
                    sk_srgb_singleton());

    BitFlags bits = info.fPaintBits;
    SkPaint::TextEncoding encoding = dst->getTextEncoding();

    if (0 == bits) {
        return;
    }
    if (kEntirePaint_Bits == bits) {
        // we've already computed these, so save it from the assignment
        uint32_t f = dst->getFlags();
        SkColor4f c = dst->getColor4f();
        *dst = src;
        dst->setFlags(f);
        dst->setColor4f(c, sk_srgb_singleton());
        dst->setTextEncoding(encoding);
        return;
    }

    if (bits & kStyle_Bit) {
        dst->setStyle(src.getStyle());
        dst->setStrokeWidth(src.getStrokeWidth());
        dst->setStrokeMiter(src.getStrokeMiter());
        dst->setStrokeCap(src.getStrokeCap());
        dst->setStrokeJoin(src.getStrokeJoin());
    }

    if (bits & kTextSkewX_Bit) {
        dst->setTextSkewX(src.getTextSkewX());
    }

    if (bits & kPathEffect_Bit) {
        dst->setPathEffect(src.refPathEffect());
    }
    if (bits & kMaskFilter_Bit) {
        dst->setMaskFilter(src.refMaskFilter());
    }
    if (bits & kShader_Bit) {
        dst->setShader(src.refShader());
    }
    if (bits & kColorFilter_Bit) {
        dst->setColorFilter(src.refColorFilter());
    }
    if (bits & kXfermode_Bit) {
        dst->setBlendMode(src.getBlendMode());
    }

    // we don't override these
#if 0
    dst->setTypeface(src.getTypeface());
    dst->setTextSize(src.getTextSize());
    dst->setTextScaleX(src.getTextScaleX());
    dst->setRasterizer(src.getRasterizer());
    dst->setLooper(src.getLooper());
    dst->setTextEncoding(src.getTextEncoding());
    dst->setHinting(src.getHinting());
#endif
}
Example #20
0
void GrTextUtils::DrawDFText(GrAtlasTextBlob* blob, int runIndex,
                             GrBatchFontCache* fontCache, const SkSurfaceProps& props,
                             const SkPaint& skPaint, GrColor color,
                             const SkMatrix& viewMatrix,
                             const char text[], size_t byteLength,
                             SkScalar x, SkScalar y) {
    SkASSERT(byteLength == 0 || text != nullptr);

    // nothing to draw
    if (text == nullptr || byteLength == 0) {
        return;
    }

    SkPaint::GlyphCacheProc glyphCacheProc = skPaint.getGlyphCacheProc(true);
    SkAutoDescriptor desc;
    skPaint.getScalerContextDescriptor(&desc, props, SkPaint::FakeGamma::Off, nullptr);
    SkGlyphCache* origPaintCache = SkGlyphCache::DetachCache(skPaint.getTypeface(),
                                                             desc.getDesc());

    SkTArray<SkScalar> positions;

    const char* textPtr = text;
    SkFixed stopX = 0;
    SkFixed stopY = 0;
    SkFixed origin = 0;
    switch (skPaint.getTextAlign()) {
        case SkPaint::kRight_Align: origin = SK_Fixed1; break;
        case SkPaint::kCenter_Align: origin = SK_FixedHalf; break;
        case SkPaint::kLeft_Align: origin = 0; break;
    }

    SkAutoKern autokern;
    const char* stop = text + byteLength;
    while (textPtr < stop) {
        // don't need x, y here, since all subpixel variants will have the
        // same advance
        const SkGlyph& glyph = glyphCacheProc(origPaintCache, &textPtr);

        SkFixed width = glyph.fAdvanceX + autokern.adjust(glyph);
        positions.push_back(SkFixedToScalar(stopX + SkFixedMul(origin, width)));

        SkFixed height = glyph.fAdvanceY;
        positions.push_back(SkFixedToScalar(stopY + SkFixedMul(origin, height)));

        stopX += width;
        stopY += height;
    }
    SkASSERT(textPtr == stop);

    SkGlyphCache::AttachCache(origPaintCache);

    // now adjust starting point depending on alignment
    SkScalar alignX = SkFixedToScalar(stopX);
    SkScalar alignY = SkFixedToScalar(stopY);
    if (skPaint.getTextAlign() == SkPaint::kCenter_Align) {
        alignX = SkScalarHalf(alignX);
        alignY = SkScalarHalf(alignY);
    } else if (skPaint.getTextAlign() == SkPaint::kLeft_Align) {
        alignX = 0;
        alignY = 0;
    }
    x -= alignX;
    y -= alignY;
    SkPoint offset = SkPoint::Make(x, y);

    DrawDFPosText(blob, runIndex, fontCache, props, skPaint, color, viewMatrix, text, byteLength,
                  positions.begin(), 2, offset);
}
Example #21
0
void SimpleFontData::platformInit()
{
    if (!m_platformData.size()) {
        m_fontMetrics.reset();
        m_avgCharWidth = 0;
        m_maxCharWidth = 0;
        return;
    }

    SkPaint paint;
    SkPaint::FontMetrics metrics;

    m_platformData.setupPaint(&paint);
    paint.getFontMetrics(&metrics);
    SkTypeface* face = paint.getTypeface();
    ASSERT(face);

    int vdmxAscent = 0, vdmxDescent = 0;
    bool isVDMXValid = false;

#if OS(LINUX) || OS(ANDROID)
    // Manually digging up VDMX metrics is only applicable when bytecode hinting using FreeType.
    // With DirectWrite or CoreText, no bytecode hinting is ever done.
    // This code should be pushed into FreeType (hinted font metrics).
    static const uint32_t vdmxTag = SkSetFourByteTag('V', 'D', 'M', 'X');
    int pixelSize = m_platformData.size() + 0.5;
    if (!paint.isAutohinted()
        &&    (paint.getHinting() == SkPaint::kFull_Hinting
            || paint.getHinting() == SkPaint::kNormal_Hinting))
    {
        size_t vdmxSize = face->getTableSize(vdmxTag);
        if (vdmxSize && vdmxSize < maxVDMXTableSize) {
            uint8_t* vdmxTable = (uint8_t*)WTF::Partitions::fastMalloc(vdmxSize, WTF_HEAP_PROFILER_TYPE_NAME(SimpleFontData));
            if (vdmxTable
                && face->getTableData(vdmxTag, 0, vdmxSize, vdmxTable) == vdmxSize
                && parseVDMX(&vdmxAscent, &vdmxDescent, vdmxTable, vdmxSize, pixelSize))
                isVDMXValid = true;
            WTF::Partitions::fastFree(vdmxTable);
        }
    }
#endif

    float ascent;
    float descent;

    // Beware those who step here: This code is designed to match Win32 font
    // metrics *exactly* (except the adjustment of ascent/descent on Linux/Android).
    if (isVDMXValid) {
        ascent = vdmxAscent;
        descent = -vdmxDescent;
    } else {
        ascent = SkScalarRoundToInt(-metrics.fAscent);
        descent = SkScalarRoundToInt(metrics.fDescent);
#if OS(LINUX) || OS(ANDROID)
        // When subpixel positioning is enabled, if the descent is rounded down, the descent part
        // of the glyph may be truncated when displayed in a 'overflow: hidden' container.
        // To avoid that, borrow 1 unit from the ascent when possible.
        // FIXME: This can be removed if sub-pixel ascent/descent is supported.
        if (platformData().getFontRenderStyle().useSubpixelPositioning && descent < SkScalarToFloat(metrics.fDescent) && ascent >= 1) {
            ++descent;
            --ascent;
        }
#endif
    }

#if OS(MACOSX)
    // We are preserving this ascent hack to match Safari's ascent adjustment
    // in their SimpleFontDataMac.mm, for details see crbug.com/445830.
    // We need to adjust Times, Helvetica, and Courier to closely match the
    // vertical metrics of their Microsoft counterparts that are the de facto
    // web standard. The AppKit adjustment of 20% is too big and is
    // incorrectly added to line spacing, so we use a 15% adjustment instead
    // and add it to the ascent.
    DEFINE_STATIC_LOCAL(AtomicString, timesName, ("Times"));
    DEFINE_STATIC_LOCAL(AtomicString, helveticaName, ("Helvetica"));
    DEFINE_STATIC_LOCAL(AtomicString, courierName, ("Courier"));
    String familyName = m_platformData.fontFamilyName();
    if (familyName == timesName || familyName == helveticaName || familyName == courierName)
        ascent += floorf(((ascent + descent) * 0.15f) + 0.5f);
#endif

    m_fontMetrics.setAscent(ascent);
    m_fontMetrics.setDescent(descent);

    float xHeight;
    if (metrics.fXHeight) {
        xHeight = metrics.fXHeight;
#if OS(MACOSX)
        // Mac OS CTFontGetXHeight reports the bounding box height of x,
        // including parts extending below the baseline and apparently no x-height
        // value from the OS/2 table. However, the CSS ex unit
        // expects only parts above the baseline, hence measuring the glyph:
        // http://www.w3.org/TR/css3-values/#ex-unit
        const Glyph xGlyph = glyphForCharacter('x');
        if (xGlyph) {
            FloatRect glyphBounds(boundsForGlyph(xGlyph));
            // SkGlyph bounds, y down, based on rendering at (0,0).
            xHeight = - glyphBounds.y();
        }
#endif
        m_fontMetrics.setXHeight(xHeight);
    } else {
        xHeight = ascent * 0.56; // Best guess from Windows font metrics.
        m_fontMetrics.setXHeight(xHeight);
        m_fontMetrics.setHasXHeight(false);
    }

    float lineGap = SkScalarToFloat(metrics.fLeading);
    m_fontMetrics.setLineGap(lineGap);
    m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));

    if (platformData().isVerticalAnyUpright() && !isTextOrientationFallback()) {
        static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a');
        static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G');
        size_t vheaSize = face->getTableSize(vheaTag);
        size_t vorgSize = face->getTableSize(vorgTag);
        if ((vheaSize > 0) || (vorgSize > 0))
            m_hasVerticalGlyphs = true;
    }

    // In WebKit/WebCore/platform/graphics/SimpleFontData.cpp, m_spaceWidth is
    // calculated for us, but we need to calculate m_maxCharWidth and
    // m_avgCharWidth in order for text entry widgets to be sized correctly.
#if OS(WIN)
    m_maxCharWidth = SkScalarRoundToInt(metrics.fMaxCharWidth);

    // Older version of the DirectWrite API doesn't implement support for max
    // char width. Fall back on a multiple of the ascent. This is entirely
    // arbitrary but comes pretty close to the expected value in most cases.
    if (m_maxCharWidth < 1)
        m_maxCharWidth = ascent * 2;
#elif OS(MACOSX)
    // FIXME: The current avg/max character width calculation is not ideal,
    // it should check either the OS2 table or, better yet, query FontMetrics.
    // Sadly FontMetrics provides incorrect data on Mac at the moment.
    // https://crbug.com/420901
    m_maxCharWidth = std::max(m_avgCharWidth, m_fontMetrics.floatAscent());
#else
    // Better would be to rely on either fMaxCharWidth or fAveCharWidth.
    // skbug.com/3087
    m_maxCharWidth = SkScalarRoundToInt(metrics.fXMax - metrics.fXMin);

#endif

#if !OS(MACOSX)
    if (metrics.fAvgCharWidth) {
        m_avgCharWidth = SkScalarRoundToInt(metrics.fAvgCharWidth);
    } else {
#endif
        m_avgCharWidth = xHeight;
        const Glyph xGlyph = glyphForCharacter('x');
        if (xGlyph) {
            m_avgCharWidth = widthForGlyph(xGlyph);
        }
#if !OS(MACOSX)
    }
#endif

    if (int unitsPerEm = face->getUnitsPerEm())
        m_fontMetrics.setUnitsPerEm(unitsPerEm);
}
Example #22
0
    void onDraw(SkCanvas* canvas) override {

        canvas->drawColor(sk_tool_utils::color_to_565(SK_ColorGRAY));

        SkPaint paint;
        paint.setTypeface(emojiFont.typeface);
        const char* text = emojiFont.text;

        // draw text at different point sizes
        const int textSize[] = { 10, 30, 50, };
        const int textYOffset[] = { 10, 40, 100, };
        SkASSERT(sizeof(textSize) == sizeof(textYOffset));
        size_t y_offset = 0;
        for (size_t y = 0; y < sizeof(textSize) / sizeof(int); y++) {
            paint.setTextSize(SkIntToScalar(textSize[y]));
            canvas->drawText(text, strlen(text), 10, SkIntToScalar(textYOffset[y]), paint);
            y_offset += textYOffset[y];
        }

        // draw with shaders and image filters
        for (int makeLinear = 0; makeLinear < 2; makeLinear++) {
            for (int makeBlur = 0; makeBlur < 2; makeBlur++) {
                for (int makeGray = 0; makeGray < 2; makeGray++) {
                    SkPaint shaderPaint;
                    shaderPaint.setTypeface(paint.getTypeface());
                    if (SkToBool(makeLinear)) {
                        shaderPaint.setShader(MakeLinear())->unref();
                    }

                    if (SkToBool(makeBlur) && SkToBool(makeGray)) {
                        SkAutoTUnref<SkImageFilter> grayScale(make_grayscale(nullptr));
                        SkAutoTUnref<SkImageFilter> blur(make_blur(3.0f, grayScale));
                        shaderPaint.setImageFilter(blur);
                    } else if (SkToBool(makeBlur)) {
                        SkAutoTUnref<SkImageFilter> blur(make_blur(3.0f, nullptr));
                        shaderPaint.setImageFilter(blur);
                    } else if (SkToBool(makeGray)) {
                        SkAutoTUnref<SkImageFilter> grayScale(make_grayscale(nullptr));
                        shaderPaint.setImageFilter(grayScale);
                    }
                    shaderPaint.setTextSize(30);
                    canvas->drawText(text, strlen(text), 380, SkIntToScalar(y_offset),
                                     shaderPaint);
                    y_offset += 32;
                }
            }
        }

        // setup work needed to draw text with different clips
        canvas->translate(10, 160);
        paint.setTextSize(40);

        // compute the bounds of the text
        SkRect bounds;
        paint.measureText(text, strlen(text), &bounds);

        const SkScalar boundsHalfWidth = bounds.width() * SK_ScalarHalf;
        const SkScalar boundsHalfHeight = bounds.height() * SK_ScalarHalf;
        const SkScalar boundsQuarterWidth = boundsHalfWidth * SK_ScalarHalf;
        const SkScalar boundsQuarterHeight = boundsHalfHeight * SK_ScalarHalf;

        SkRect upperLeftClip = SkRect::MakeXYWH(bounds.left(), bounds.top(),
                                                boundsHalfWidth, boundsHalfHeight);
        SkRect lowerRightClip = SkRect::MakeXYWH(bounds.centerX(), bounds.centerY(),
                                                 boundsHalfWidth, boundsHalfHeight);
        SkRect interiorClip = bounds;
        interiorClip.inset(boundsQuarterWidth, boundsQuarterHeight);

        const SkRect clipRects[] = { bounds, upperLeftClip, lowerRightClip, interiorClip };

        SkPaint clipHairline;
        clipHairline.setColor(SK_ColorWHITE);
        clipHairline.setStyle(SkPaint::kStroke_Style);

        for (size_t x = 0; x < sizeof(clipRects) / sizeof(SkRect); ++x) {
            canvas->save();
            canvas->drawRect(clipRects[x], clipHairline);
            paint.setAlpha(0x20);
            canvas->drawText(text, strlen(text), 0, 0, paint);
            canvas->clipRect(clipRects[x]);
            paint.setAlpha(0xFF);
            canvas->drawText(text, strlen(text), 0, 0, paint);
            canvas->restore();
            canvas->translate(0, bounds.height() + SkIntToScalar(25));
        }
    }
Example #23
0
// Even with kEntirePaint_Bits, we always ensure that the master paint's
// text-encoding is respected, since that controls how we interpret the
// text/length parameters of a draw[Pos]Text call.
void SkLayerDrawLooper::ApplyInfo(SkPaint* dst, const SkPaint& src,
                                  const LayerInfo& info) {

    uint32_t mask = info.fFlagsMask;
    dst->setFlags((dst->getFlags() & ~mask) | (src.getFlags() & mask));
    dst->setColor(xferColor(src.getColor(), dst->getColor(), info.fColorMode));

    BitFlags bits = info.fPaintBits;
    SkPaint::TextEncoding encoding = dst->getTextEncoding();

    if (0 == bits) {
        return;
    }
    if (kEntirePaint_Bits == bits) {
        // we've already computed these, so save it from the assignment
        uint32_t f = dst->getFlags();
        SkColor c = dst->getColor();
        *dst = src;
        dst->setFlags(f);
        dst->setColor(c);
        dst->setTextEncoding(encoding);
        return;
    }

    if (bits & kStyle_Bit) {
        dst->setStyle(src.getStyle());
        dst->setStrokeWidth(src.getStrokeWidth());
        dst->setStrokeMiter(src.getStrokeMiter());
        dst->setStrokeCap(src.getStrokeCap());
        dst->setStrokeJoin(src.getStrokeJoin());
    }

    if (bits & kTextSkewX_Bit) {
        dst->setTextSkewX(src.getTextSkewX());
    }

    if (bits & kPathEffect_Bit) {
        dst->setPathEffect(src.getPathEffect());
    }
    if (bits & kMaskFilter_Bit) {
        dst->setMaskFilter(src.getMaskFilter());
    }
    if (bits & kShader_Bit) {
        dst->setShader(src.getShader());
    }
    if (bits & kColorFilter_Bit) {
        dst->setColorFilter(src.getColorFilter());
    }
    if (bits & kXfermode_Bit) {
        dst->setXfermode(src.getXfermode());
    }

    // we don't override these
#if 0
    dst->setTypeface(src.getTypeface());
    dst->setTextSize(src.getTextSize());
    dst->setTextScaleX(src.getTextScaleX());
    dst->setRasterizer(src.getRasterizer());
    dst->setLooper(src.getLooper());
    dst->setTextEncoding(src.getTextEncoding());
    dst->setHinting(src.getHinting());
#endif
}
Example #24
0
    virtual void onDrawContent(SkCanvas* canvas) {
        canvas->translate(SkIntToScalar(10), SkIntToScalar(20));

        if (false) {
            SkPaint paint;
            paint.setAntiAlias(true);
            paint.setTextSize(50);
            paint.setTypeface(SkTypeface::CreateFromName("Arial Unicode MS", SkTypeface::kNormal));
            SkSafeUnref(paint.getTypeface());
            char buffer[10];
            size_t len = SkUTF8_FromUnichar(0x8500, buffer);
            canvas->drawText(buffer, len, 40, 40, paint);
            return;
        }
        if (false) {
            SkPaint paint;
            paint.setAntiAlias(true);

            SkRect r0 = { 0, 0, 10.5f, 20 };
            SkRect r1 = { 10.5f, 10, 20, 30 };
            paint.setColor(SK_ColorRED);
            canvas->drawRect(r0, paint);
            paint.setColor(SK_ColorBLUE);
            canvas->drawRect(r1, paint);
            return;
        }

        const struct {
            SkXfermode::Mode  fMode;
            const char*         fLabel;
        } gModes[] = {
            { SkXfermode::kClear_Mode,    "Clear"     },
            { SkXfermode::kSrc_Mode,      "Src"       },
            { SkXfermode::kDst_Mode,      "Dst"       },
            { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
            { SkXfermode::kDstOver_Mode,  "DstOver"   },
            { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
            { SkXfermode::kDstIn_Mode,    "DstIn"     },
            { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
            { SkXfermode::kDstOut_Mode,   "DstOut"    },
            { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
            { SkXfermode::kDstATop_Mode,  "DstATop"   },
            { SkXfermode::kXor_Mode,      "Xor"       },

            { SkXfermode::kPlus_Mode,         "Plus"          },
            /*{ SkXfermode::kModulate_Mode,     "Modulate"      },
            { SkXfermode::kScreen_Mode,       "Screen"        },
            { SkXfermode::kOverlay_Mode,      "Overlay"       },
            { SkXfermode::kDarken_Mode,       "Darken"        },
            { SkXfermode::kLighten_Mode,      "Lighten"       },
            { SkXfermode::kColorDodge_Mode,   "ColorDodge"    },
            { SkXfermode::kColorBurn_Mode,    "ColorBurn"     },
            { SkXfermode::kHardLight_Mode,    "HardLight"     },
            { SkXfermode::kSoftLight_Mode,    "SoftLight"     },
            { SkXfermode::kDifference_Mode,   "Difference"    },
            { SkXfermode::kExclusion_Mode,    "Exclusion"     },*/
        };

        const SkScalar w = SkIntToScalar(W);
        const SkScalar h = SkIntToScalar(H);
        SkShader* s = SkShader::CreateBitmapShader(fBG,
                                                   SkShader::kRepeat_TileMode,
                                                   SkShader::kRepeat_TileMode);
        SkMatrix m;
        m.setScale(SkIntToScalar(6), SkIntToScalar(6));
        s->setLocalMatrix(m);

        SkPaint labelP;
        labelP.setAntiAlias(true);
        labelP.setLCDRenderText(true);
        labelP.setTextAlign(SkPaint::kCenter_Align);
        setNamedTypeface(&labelP, "Menlo Regular");

        const int W = 5;

        SkScalar x0 = 0;
        for (int twice = 0; twice < 2; twice++) {
            SkScalar x = x0, y = 0;
            for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
                SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
                SkAutoUnref aur(mode);
                SkRect r;
                r.set(x, y, x+w, y+h);

                SkPaint p;
                p.setStyle(SkPaint::kFill_Style);
                p.setShader(s);
                canvas->drawRect(r, p);

                canvas->saveLayer(&r, NULL);
                draw_mode(canvas, mode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
                canvas->restore();

                r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
                p.setStyle(SkPaint::kStroke_Style);
                p.setShader(NULL);
                canvas->drawRect(r, p);

                canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel),
                                 x + w/2, y - labelP.getTextSize()/2, labelP);
                x += w + SkIntToScalar(10);
                if ((i % W) == W - 1) {
                    x = x0;
                    y += h + SkIntToScalar(30);
                }
            }
            x0 += SkIntToScalar(400);
        }
        s->unref();
    }
Example #25
0
void SkFlatPaint::dump() const {
    SkPaint defaultPaint;
    SkFlattenableReadBuffer buffer(fPaintData);
    SkTypeface* typeface = (SkTypeface*) buffer.readPtr();
    char pBuffer[DUMP_BUFFER_SIZE];
    char* bufferPtr = pBuffer;
    bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
        "paint: ");
    if (typeface != defaultPaint.getTypeface())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "typeface:%p ", typeface);
    SkScalar textSize = buffer.readScalar();
    if (textSize != defaultPaint.getTextSize())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "textSize:%g ", SkScalarToFloat(textSize));
    SkScalar textScaleX = buffer.readScalar();
    if (textScaleX != defaultPaint.getTextScaleX())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "textScaleX:%g ", SkScalarToFloat(textScaleX));
    SkScalar textSkewX = buffer.readScalar();
    if (textSkewX != defaultPaint.getTextSkewX())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "textSkewX:%g ", SkScalarToFloat(textSkewX));
    const SkPathEffect* pathEffect = (const SkPathEffect*) buffer.readFlattenable();
    if (pathEffect != defaultPaint.getPathEffect())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "pathEffect:%p ", pathEffect);
    SkDELETE(pathEffect);
    const SkShader* shader = (const SkShader*) buffer.readFlattenable();
    if (shader != defaultPaint.getShader())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "shader:%p ", shader);
    SkDELETE(shader);
    const SkXfermode* xfermode = (const SkXfermode*) buffer.readFlattenable();
    if (xfermode != defaultPaint.getXfermode())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "xfermode:%p ", xfermode);
    SkDELETE(xfermode);
    const SkMaskFilter* maskFilter = (const SkMaskFilter*) buffer.readFlattenable();
    if (maskFilter != defaultPaint.getMaskFilter())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "maskFilter:%p ", maskFilter);
    SkDELETE(maskFilter);
    const SkColorFilter* colorFilter = (const SkColorFilter*) buffer.readFlattenable();
    if (colorFilter != defaultPaint.getColorFilter())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "colorFilter:%p ", colorFilter);
    SkDELETE(colorFilter);
    const SkRasterizer* rasterizer = (const SkRasterizer*) buffer.readFlattenable();
    if (rasterizer != defaultPaint.getRasterizer())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "rasterizer:%p ", rasterizer);
    SkDELETE(rasterizer);
    const SkDrawLooper* drawLooper = (const SkDrawLooper*) buffer.readFlattenable();
    if (drawLooper != defaultPaint.getLooper())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "drawLooper:%p ", drawLooper);
    SkDELETE(drawLooper);
    unsigned color = buffer.readU32();
    if (color != defaultPaint.getColor())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "color:0x%x ", color);
    SkScalar strokeWidth = buffer.readScalar();
    if (strokeWidth != defaultPaint.getStrokeWidth())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "strokeWidth:%g ", SkScalarToFloat(strokeWidth));
    SkScalar strokeMiter = buffer.readScalar();
    if (strokeMiter != defaultPaint.getStrokeMiter())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "strokeMiter:%g ", SkScalarToFloat(strokeMiter));
    unsigned flags = buffer.readU16();
    if (flags != defaultPaint.getFlags())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "flags:0x%x ", flags);
    int align = buffer.readU8();
    if (align != defaultPaint.getTextAlign())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "align:0x%x ", align);
    int strokeCap = buffer.readU8();
    if (strokeCap != defaultPaint.getStrokeCap())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "strokeCap:0x%x ", strokeCap);
    int strokeJoin = buffer.readU8();
    if (strokeJoin != defaultPaint.getStrokeJoin())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "align:0x%x ", strokeJoin);
    int style = buffer.readU8();
    if (style != defaultPaint.getStyle())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "style:0x%x ", style);
    int textEncoding = buffer.readU8();
    if (textEncoding != defaultPaint.getTextEncoding())
        bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), 
            "textEncoding:0x%x ", textEncoding);
    SkDebugf("%s\n", pBuffer);
}