예제 #1
0
void SkDumpCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
                              const SkPaint& paint) {
    SkString str;
    toString(text, byteLength, paint.getTextEncoding(), &str);
    this->dump(kDrawText_Verb, &paint, "drawText(%s [%d] %g %g)", str.c_str(),
               byteLength, SkScalarToFloat(x), SkScalarToFloat(y));
}
예제 #2
0
void SkDumpCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
                                    const SkMatrix* matrix, const SkPaint& paint) {
    SkString str;
    toString(text, byteLength, paint.getTextEncoding(), &str);
    this->dump(kDrawText_Verb, &paint, "drawTextOnPath(%s [%d])",
               str.c_str(), byteLength);
}
예제 #3
0
void SkOverdrawCanvas::onDrawTextRSXform(const void* text, size_t byteLength,
                                         const SkRSXform xform[], const SkRect*,
                                         const SkPaint& paint) {
    CountTextProc proc = nullptr;
    switch (paint.getTextEncoding()) {
        case SkPaint::kUTF8_TextEncoding:
            proc = SkUTF8_CountUTF8Bytes;
            break;
        case SkPaint::kUTF16_TextEncoding:
            proc = count_utf16;
            break;
        case SkPaint::kUTF32_TextEncoding:
            proc = return_4;
            break;
        case SkPaint::kGlyphID_TextEncoding:
            proc = return_2;
            break;
    }
    SkASSERT(proc);

    SkMatrix matrix;
    const void* stopText = (const char*)text + byteLength;
    while ((const char*)text < (const char*)stopText) {
        matrix.setRSXform(*xform++);
        matrix.setConcat(this->getTotalMatrix(), matrix);
        int subLen = proc((const char*)text);

        this->save();
        this->concat(matrix);
        this->drawText(text, subLen, 0, 0, paint);
        this->restore();

        text = (const char*)text + subLen;
    }
}
예제 #4
0
void SkDumpCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
                                     const SkRect* cull, const SkPaint& paint) {
    SkString str;
    toString(text, byteLength, paint.getTextEncoding(), &str);
    this->dump(kDrawText_Verb, &paint, "drawTextRSXform(%s [%d])",
               str.c_str(), byteLength);
}
예제 #5
0
파일: SkDevice.cpp 프로젝트: OwenTan/skia
void SkBaseDevice::drawTextRSXform(const SkDraw& draw, const void* text, size_t len,
                                   const SkRSXform xform[], const SkPaint& paint) {
    CountTextProc proc = nullptr;
    switch (paint.getTextEncoding()) {
        case SkPaint::kUTF8_TextEncoding:
            proc = SkUTF8_CountUTF8Bytes;
            break;
        case SkPaint::kUTF16_TextEncoding:
            proc = count_utf16;
            break;
        case SkPaint::kUTF32_TextEncoding:
            proc = return_4;
            break;
        case SkPaint::kGlyphID_TextEncoding:
            proc = return_2;
            break;
    }

    SkDraw localD(draw);
    SkMatrix localM, currM;
    const void* stopText = (const char*)text + len;
    while ((const char*)text < (const char*)stopText) {
        localM.setRSXform(*xform++);
        currM.setConcat(*draw.fMatrix, localM);
        localD.fMatrix = &currM;
        int subLen = proc((const char*)text);
        this->drawText(localD, text, subLen, 0, 0, paint);
        text = (const char*)text + subLen;
    }
}
예제 #6
0
void SkDumpCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
                                  SkScalar constY, const SkPaint& paint) {
    SkString str;
    toString(text, byteLength, paint.getTextEncoding(), &str);
    this->dump(kDrawText_Verb, &paint, "drawPosTextH(%s [%d] %g %g ...)",
               str.c_str(), byteLength, SkScalarToFloat(xpos[0]),
               SkScalarToFloat(constY));
}
예제 #7
0
void SkOverdrawCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
                                  const SkPaint& paint) {
    ProcessOneGlyphBounds processBounds(this);
    SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
    this->getProps(&props);
    auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(
            paint, &props, SkScalerContextFlags::kNone, &this->getTotalMatrix());
    SkFindAndPlaceGlyph::ProcessText(paint.getTextEncoding(), (const char*) text, byteLength,
                                     SkPoint::Make(x, y), SkMatrix(), paint.getTextAlign(),
                                     cache.get(), processBounds);
}
예제 #8
0
static void getGlyphPositions(const SkPaint& paint, const uint16_t glyphs[],
                             int count, SkScalar x, SkScalar y, SkPoint pos[]) {
    SkASSERT(SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding());

    SkAutoSTMalloc<128, SkScalar> widthStorage(count);
    SkScalar* widths = widthStorage.get();
    paint.getTextWidths(glyphs, count * sizeof(uint16_t), widths);

    for (int i = 0; i < count; ++i) {
        pos[i].set(x, y);
        x += widths[i];
    }
}
예제 #9
0
SkDrawTextCommand::SkDrawTextCommand(const void* text, size_t byteLength, SkScalar x, SkScalar y,
                                     const SkPaint& paint)
    : INHERITED(DRAW_TEXT) {
    fText = new char[byteLength];
    memcpy(fText, text, byteLength);
    fByteLength = byteLength;
    fX = x;
    fY = y;
    fPaint = paint;

    fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
    fInfo.push(SkObjectParser::ScalarToString(x, "SkScalar x: "));
    fInfo.push(SkObjectParser::ScalarToString(y, "SkScalar y: "));
    fInfo.push(SkObjectParser::PaintToString(paint));
}
예제 #10
0
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");
}
예제 #11
0
    static int breakText(JNIEnv* env, const SkPaint& paint, const jchar text[],
                         int count, float maxWidth, jfloatArray jmeasured,
                         SkPaint::TextBufferDirection tbd) {
        SkASSERT(paint.getTextEncoding() == SkPaint::kUTF16_TextEncoding);

        SkScalar     measured;
        size_t       bytes = paint.breakText(text, count << 1,
                                   SkFloatToScalar(maxWidth), &measured, tbd);
        SkASSERT((bytes & 1) == 0);

        if (jmeasured && env->GetArrayLength(jmeasured) > 0) {
            AutoJavaFloatArray autoMeasured(env, jmeasured, 1);
            jfloat* array = autoMeasured.ptr();
            array[0] = SkScalarToFloat(measured);
        }
        return bytes >> 1;
    }
예제 #12
0
파일: SkDevice.cpp 프로젝트: vschs007/skia
void SkBaseDevice::drawTextRSXform(const void* text, size_t len,
                                   const SkRSXform xform[], const SkPaint& paint) {
    CountTextProc proc = nullptr;
    switch (paint.getTextEncoding()) {
        case SkPaint::kUTF8_TextEncoding:
            proc = SkUTF8_CountUTF8Bytes;
            break;
        case SkPaint::kUTF16_TextEncoding:
            proc = count_utf16;
            break;
        case SkPaint::kUTF32_TextEncoding:
            proc = return_4;
            break;
        case SkPaint::kGlyphID_TextEncoding:
            proc = return_2;
            break;
    }

    SkPaint localPaint(paint);
    SkShader* shader = paint.getShader();

    SkMatrix localM, currM;
    const void* stopText = (const char*)text + len;
    while ((const char*)text < (const char*)stopText) {
        localM.setRSXform(*xform++);
        currM.setConcat(this->ctm(), localM);
        SkAutoDeviceCTMRestore adc(this, currM);

        // We want to rotate each glyph by the rsxform, but we don't want to rotate "space"
        // (i.e. the shader that cares about the ctm) so we have to undo our little ctm trick
        // with a localmatrixshader so that the shader draws as if there was no change to the ctm.
        if (shader) {
            SkMatrix inverse;
            if (localM.invert(&inverse)) {
                localPaint.setShader(shader->makeWithLocalMatrix(inverse));
            } else {
                localPaint.setShader(nullptr);  // can't handle this xform
            }
        }

        int subLen = proc((const char*)text);
        this->drawText(text, subLen, 0, 0, localPaint);
        text = (const char*)text + subLen;
    }
}
예제 #13
0
String LoggingCanvas::stringForText(const void* text, size_t byteLength, const SkPaint& paint)
{
    SkPaint::TextEncoding encoding = paint.getTextEncoding();
    switch (encoding) {
    case SkPaint::kUTF8_TextEncoding:
    case SkPaint::kUTF16_TextEncoding:
    case SkPaint::kUTF32_TextEncoding:
        return stringForUTFText(text, byteLength, encoding);
    case SkPaint::kGlyphID_TextEncoding: {
        WTF::Vector<SkUnichar> dataVector(byteLength / 2);
        SkUnichar* textData = dataVector.data();
        paint.glyphsToUnichars(static_cast<const uint16_t*>(text), byteLength / 2, textData);
        return WTF::UTF32LittleEndianEncoding().decode(reinterpret_cast<const char*>(textData), byteLength * 2);
    }
    default:
        ASSERT_NOT_REACHED();
        return "?";
    }
}
예제 #14
0
SkDrawPosTextCommand::SkDrawPosTextCommand(const void* text, size_t byteLength,
                                           const SkPoint pos[], const SkPaint& paint)
    : INHERITED(DRAW_POS_TEXT) {
    size_t numPts = paint.countText(text, byteLength);

    fText = new char[byteLength];
    memcpy(fText, text, byteLength);
    fByteLength = byteLength;

    fPos = new SkPoint[numPts];
    memcpy(fPos, pos, numPts * sizeof(SkPoint));

    fPaint = paint;

    fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
    // TODO(chudy): Test that this works.
    fInfo.push(SkObjectParser::PointsToString(pos, 1));
    fInfo.push(SkObjectParser::PaintToString(paint));
}
예제 #15
0
void FindCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
                          SkScalar y, const SkPaint& paint) {

   SkPaint::TextEncoding encoding = paint.getTextEncoding();
   //For complex text, transform utf16 to glyph
   if (encoding == SkPaint::kUTF16_TextEncoding) {
     int mCount = 0;
     uint16_t *glyphBuf = NULL;
     glyphBuf = new uint16_t[byteLength];
     mCount = paint.textToGlyphs(text, byteLength, glyphBuf, byteLength);
     
     SkPaint clonePaint(paint);
     clonePaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
     findHelper(glyphBuf, 2*mCount, clonePaint, &x, y, &FindCanvas::addMatchNormal);
     delete glyphBuf;
     return;
   }

    findHelper(text, byteLength, paint, &x, y, &FindCanvas::addMatchNormal);
}
예제 #16
0
void GrTextUtils::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex,
                                 GrBatchFontCache* fontCache,
                                 const SkSurfaceProps& props, const SkPaint& skPaint,
                                 GrColor color,
                                 const SkMatrix& viewMatrix,
                                 const char text[], size_t byteLength,
                                 const SkScalar pos[], int scalarsPerPosition,
                                 const SkPoint& offset) {
    SkASSERT(byteLength == 0 || text != nullptr);
    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);

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

    // Ensure the blob is set for bitmaptext
    blob->setHasBitmap();

    GrBatchTextStrike* currStrike = nullptr;

    // Get GrFontScaler from cache
    SkGlyphCache* cache = blob->setupCache(runIndex, props, SkPaint::FakeGamma::On,
                                           skPaint, &viewMatrix);
    GrFontScaler* fontScaler = GrTextUtils::GetGrFontScaler(cache);

    SkFindAndPlaceGlyph::ProcessPosText(
        skPaint.getTextEncoding(), text, byteLength,
        offset, viewMatrix, pos, scalarsPerPosition,
        skPaint.getTextAlign(), cache,
        [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
            position += rounding;
            BmpAppendGlyph(
                blob, runIndex, fontCache, &currStrike, glyph,
                SkScalarFloorToInt(position.fX), SkScalarFloorToInt(position.fY),
                color, fontScaler);
        }
    );

    SkGlyphCache::AttachCache(cache);
}
예제 #17
0
PassRefPtr<JSONObject> LoggingCanvas::objectForSkPaint(const SkPaint& paint)
{
    RefPtr<JSONObject> paintItem = JSONObject::create();
    paintItem->setNumber("textSize", paint.getTextSize());
    paintItem->setNumber("textScaleX", paint.getTextScaleX());
    paintItem->setNumber("textSkewX", paint.getTextSkewX());
    if (SkShader* shader = paint.getShader())
        paintItem->setObject("shader", objectForSkShader(*shader));
    paintItem->setString("color", stringForSkColor(paint.getColor()));
    paintItem->setNumber("strokeWidth", paint.getStrokeWidth());
    paintItem->setNumber("strokeMiter", paint.getStrokeMiter());
    paintItem->setString("flags", stringForSkPaintFlags(paint));
    paintItem->setString("filterLevel", filterQualityName(paint.getFilterQuality()));
    paintItem->setString("textAlign", textAlignName(paint.getTextAlign()));
    paintItem->setString("strokeCap", strokeCapName(paint.getStrokeCap()));
    paintItem->setString("strokeJoin", strokeJoinName(paint.getStrokeJoin()));
    paintItem->setString("styleName", styleName(paint.getStyle()));
    paintItem->setString("textEncoding", textEncodingName(paint.getTextEncoding()));
    paintItem->setString("hinting", hintingName(paint.getHinting()));
    return paintItem.release();
}
예제 #18
0
SkDrawPosTextHCommand::SkDrawPosTextHCommand(const void* text, size_t byteLength,
                                             const SkScalar xpos[], SkScalar constY,
                                             const SkPaint& paint)
    : INHERITED(DRAW_POS_TEXT_H) {
    size_t numPts = paint.countText(text, byteLength);

    fText = new char[byteLength];
    memcpy(fText, text, byteLength);
    fByteLength = byteLength;

    fXpos = new SkScalar[numPts];
    memcpy(fXpos, xpos, numPts * sizeof(SkScalar));

    fConstY = constY;
    fPaint = paint;

    fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
    fInfo.push(SkObjectParser::ScalarToString(xpos[0], "XPOS: "));
    fInfo.push(SkObjectParser::ScalarToString(constY, "SkScalar constY: "));
    fInfo.push(SkObjectParser::PaintToString(paint));
}
예제 #19
0
SkDrawTextOnPathCommand::SkDrawTextOnPathCommand(const void* text, size_t byteLength,
                                                 const SkPath& path, const SkMatrix* matrix,
                                                 const SkPaint& paint)
    : INHERITED(DRAW_TEXT_ON_PATH) {
    fText = new char[byteLength];
    memcpy(fText, text, byteLength);
    fByteLength = byteLength;
    fPath = path;
    if (NULL != matrix) {
        fMatrix = *matrix;
    } else {
        fMatrix.setIdentity();
    }
    fPaint = paint;

    fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
    fInfo.push(SkObjectParser::PathToString(path));
    if (NULL != matrix) {
        fInfo.push(SkObjectParser::MatrixToString(*matrix));
    }
    fInfo.push(SkObjectParser::PaintToString(paint));
}
예제 #20
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);
}
예제 #21
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::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
}
예제 #22
0
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);
        }
    }
}
예제 #23
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);
}
예제 #24
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
}
예제 #25
0
void FindCanvas::findHelper(const void* text, size_t byteLength,
                          const SkPaint& paint, const SkScalar positions[], 
                          SkScalar y,
                          SkRect (FindCanvas::*addMatch)(int index,
                          const SkPaint& paint, int count,
                          const uint16_t* glyphs,
                          const SkScalar positions[], SkScalar y)) {
    SkASSERT(paint.getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
    SkASSERT(mMatches);
    GlyphSet* glyphSet = getGlyphs(paint);
    const int count = glyphSet->getCount();
    int numCharacters = byteLength >> 1;
    const uint16_t* chars = (const uint16_t*) text;
    // This block will check to see if we are continuing from another line.  If
    // so, the user needs to have added a space, which we do not draw.
    if (mWorkingIndex) {
        SkPoint newY;
        getTotalMatrix().mapXY(0, y, &newY);
        SkIRect workingBounds = mWorkingRegion.getBounds();
        int newYInt = SkScalarRound(newY.fY);
        if (workingBounds.fTop > newYInt) {
            // The new text is above the working region, so we know it's not
            // a continuation.
            resetWorkingCanvas();
            mWorkingIndex = 0;
            mWorkingRegion.setEmpty();
        } else if (workingBounds.fBottom < newYInt) {
            // Now we know that this line is lower than our partial match.
            SkPaint clonePaint(paint);
            clonePaint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
            uint16_t space;
            clonePaint.textToGlyphs(" ", 1, &space);
            if (glyphSet->characterMatches(space, mWorkingIndex)) {
                mWorkingIndex++;
                if (mWorkingIndex == count) {
                    // We already know that it is not clipped out because we
                    // checked for that before saving the working region.
                    insertMatchInfo(mWorkingRegion);

                    resetWorkingCanvas();
                    mWorkingIndex = 0;
                    mWorkingRegion.setEmpty();
                    // We have found a match, so continue on this line from
                    // scratch.
                }
            } else {
                resetWorkingCanvas();
                mWorkingIndex = 0;
                mWorkingRegion.setEmpty();
            }
        }
        // If neither one is true, then we are likely continuing on the same
        // line, but are in a new draw call because the paint has changed.  In
        // this case, we can continue without adding a space.
    }
    // j is the position in the search text
    // Start off with mWorkingIndex in case we are continuing from a prior call
    int j = mWorkingIndex;
    // index is the position in the drawn text
    int index = 0;
    for ( ; index != numCharacters; index++) {
        if (glyphSet->characterMatches(chars[index], j)) {
            // The jth character in the search text matches the indexth position
            // in the drawn text, so increase j.
            j++;
            if (j != count) {
                continue;
            }
            // The last count characters match, so we found the entire
            // search string.
            int remaining = count - mWorkingIndex;
            int matchIndex = index - remaining + 1;
            // Set up a pointer to the matching text in 'chars'.
            const uint16_t* glyphs = chars + matchIndex;
            SkRect rect = (this->*addMatch)(matchIndex, paint,
                    remaining, glyphs, positions, y);
            // We need an SkIRect for SkRegion operations.
            SkIRect iRect;
            rect.roundOut(&iRect);
            // If the rectangle is partially clipped, assume that the text is
            // not visible, so skip this match.
            if (getTotalClip().contains(iRect)) {
                // Want to outset the drawn rectangle by the same amount as
                // mOutset
                iRect.inset(-INTEGER_OUTSET, -INTEGER_OUTSET);
                SkRegion regionToAdd(iRect);
                if (!mWorkingRegion.isEmpty()) {
                    // If this is on the same line as our working region, make
                    // sure that they are close enough together that they are
                    // supposed to be part of the same text string.
                    // The width of two spaces has arbitrarily been chosen.
                    const SkIRect& workingBounds = mWorkingRegion.getBounds();
                    if (workingBounds.fTop <= iRect.fBottom &&
                            workingBounds.fBottom >= iRect.fTop &&
                            SkIntToScalar(iRect.fLeft - workingBounds.fRight) > 
                            approximateSpaceWidth(paint)) {
                        index = -1;     // Will increase to 0 on next run
                        // In this case, we need to start from the beginning of
                        // the text being searched and our search term.
                        j = 0;
                        mWorkingIndex = 0;
                        mWorkingRegion.setEmpty();
                        continue;
                    }
                    // Add the mWorkingRegion, which contains rectangles from
                    // the previous line(s).
                    regionToAdd.op(mWorkingRegion, SkRegion::kUnion_Op);
                }
                insertMatchInfo(regionToAdd);
#if INCLUDE_SUBSTRING_MATCHES
                // Reset index to the location of the match and reset j to the
                // beginning, so that on the next iteration of the loop, index
                // will advance by 1 and we will compare the next character in
                // chars to the first character in the GlyphSet.
                index = matchIndex;
#endif
            } else {
                // This match was clipped out, so begin looking at the next
                // character from our hidden match
                index = matchIndex;
            }
            // Whether the clip contained it or not, we need to start over
            // with our recording canvas
            resetWorkingCanvas();
        } else {
            // Index needs to be set to index - j + 1.
            // This is a ridiculous case, but imagine the situation where the
            // user is looking for the string "jjog" in the drawText call for
            // "jjjog".  The first two letters match.  However, when the index
            // is 2, and we discover that 'o' and 'j' do not match, we should go
            // back to 1, where we do, in fact, have a match
            // FIXME: This does not work if (as in our example) "jj" is in one
            // draw call and "jog" is in the next.  Doing so would require a
            // stack, keeping track of multiple possible working indeces and
            // regions.  This is likely an uncommon case.
            index = index - j;  // index will be increased by one on the next
                                // iteration
        }
        // We reach here in one of two cases:
        // 1) We just completed a match, so any working rectangle/index is no
        // longer needed, and we will start over from the beginning
        // 2) The glyphs do not match, so we start over at the beginning of
        // the search string.
        j = 0;
        mWorkingIndex = 0;
        mWorkingRegion.setEmpty();
    }
    // At this point, we have searched all of the text in the current drawText
    // call.
    // Keep track of a partial match that may start on this line.
    if (j > 0) {    // if j is greater than 0, we have a partial match
        int relativeCount = j - mWorkingIndex;  // Number of characters in this
                                                // part of the match.
        int partialIndex = index - relativeCount; // Index that starts our
                                                  // partial match.
        const uint16_t* partialGlyphs = chars + partialIndex;
        SkRect partial = (this->*addMatch)(partialIndex, paint, relativeCount,
                partialGlyphs, positions, y);
        partial.inset(mOutset, mOutset);
        SkIRect dest;
        partial.roundOut(&dest);
        // Only save a partial if it is in the current clip.
        if (getTotalClip().contains(dest)) {
            mWorkingRegion.op(dest, SkRegion::kUnion_Op);
            mWorkingIndex = j;
            return;
        }
    }
    // This string doesn't go into the next drawText, so reset our working
    // variables
    mWorkingRegion.setEmpty();
    mWorkingIndex = 0;
}
예제 #26
0
static SkTypeface::Encoding paint2encoding(const SkPaint& paint) {
    SkPaint::TextEncoding enc = paint.getTextEncoding();
    SkASSERT(SkPaint::kGlyphID_TextEncoding != enc);
    return (SkTypeface::Encoding)enc;
}