SK_API sk_sp<SkFontMgr> SkFontMgr_New_FCI(sk_sp<SkFontConfigInterface> fci) {
    SkASSERT(fci);
    return sk_make_sp<SkFontMgr_FCI>(std::move(fci));
}
Ejemplo n.º 2
0
void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
                                   const char text[], size_t byteLength,
                                   SkScalar x, SkScalar y) {
    SkASSERT(byteLength == 0 || text != NULL);

    // nothing to draw
    if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) {
        return;
    }

    this->init(paint, skPaint);

    if (NULL == fDrawTarget) {
        return;
    }

    SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();

    SkAutoGlyphCache    autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix());
    SkGlyphCache*       cache = autoCache.getCache();
    GrFontScaler*       fontScaler = GetGrFontScaler(cache);
    if (NULL == fStrike) {
        fStrike = fContext->getFontCache()->getStrike(fontScaler, false);
    }

    // transform our starting point
    {
        SkPoint loc;
        fContext->getMatrix().mapXY(x, y, &loc);
        x = loc.fX;
        y = loc.fY;
    }

    // need to measure first
    if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
        SkVector    stop;

        MeasureText(cache, glyphCacheProc, text, byteLength, &stop);

        SkScalar    stopX = stop.fX;
        SkScalar    stopY = stop.fY;

        if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
            stopX = SkScalarHalf(stopX);
            stopY = SkScalarHalf(stopY);
        }
        x -= stopX;
        y -= stopY;
    }

    const char* stop = text + byteLength;

    // allocate vertices
    SkASSERT(NULL == fVertices);
    bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat();
    if (useColorVerts) {
        fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
                                                    SK_ARRAY_COUNT(gTextVertexWithColorAttribs));
    } else {
        fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
                                                    SK_ARRAY_COUNT(gTextVertexAttribs));
    }
    int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
    bool success = fDrawTarget->reserveVertexAndIndexSpace(4*numGlyphs,
                                                           0,
                                                           &fVertices,
                                                           NULL);
    GrAlwaysAssert(success);

    SkAutoKern autokern;

    SkFixed fxMask = ~0;
    SkFixed fyMask = ~0;
    SkFixed halfSampleX, halfSampleY;
    if (cache->isSubpixel()) {
        halfSampleX = halfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
        SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(fContext->getMatrix());
        if (kX_SkAxisAlignment == baseline) {
            fyMask = 0;
            halfSampleY = SK_FixedHalf;
        } else if (kY_SkAxisAlignment == baseline) {
            fxMask = 0;
            halfSampleX = SK_FixedHalf;
        }
    } else {
Ejemplo n.º 3
0
static inline bool skpaint_to_grpaint_impl(GrContext* context,
                                           const GrColorSpaceInfo& colorSpaceInfo,
                                           const SkPaint& skPaint,
                                           const SkMatrix& viewM,
                                           std::unique_ptr<GrFragmentProcessor>* shaderProcessor,
                                           SkBlendMode* primColorMode,
                                           GrPaint* grPaint) {
    grPaint->setAllowSRGBInputs(colorSpaceInfo.isGammaCorrect());

    // Convert SkPaint color to 4f format, including optional linearizing and gamut conversion.
    GrColor4f origColor = SkColorToUnpremulGrColor4f(skPaint.getColor(), colorSpaceInfo);

    const GrFPArgs fpArgs(context, &viewM, skPaint.getFilterQuality(), &colorSpaceInfo);

    // Setup the initial color considering the shader, the SkPaint color, and the presence or not
    // of per-vertex colors.
    std::unique_ptr<GrFragmentProcessor> shaderFP;
    if (!primColorMode || blend_requires_shader(*primColorMode)) {
        if (shaderProcessor) {
            shaderFP = std::move(*shaderProcessor);
        } else if (const auto* shader = as_SB(skPaint.getShader())) {
            shaderFP = shader->asFragmentProcessor(fpArgs);
            if (!shaderFP) {
                return false;
            }
        }
    }

    // Set this in below cases if the output of the shader/paint-color/paint-alpha/primXfermode is
    // a known constant value. In that case we can simply apply a color filter during this
    // conversion without converting the color filter to a GrFragmentProcessor.
    bool applyColorFilterToPaintColor = false;
    if (shaderFP) {
        if (primColorMode) {
            // There is a blend between the primitive color and the shader color. The shader sees
            // the opaque paint color. The shader's output is blended using the provided mode by
            // the primitive color. The blended color is then modulated by the paint's alpha.

            // The geometry processor will insert the primitive color to start the color chain, so
            // the GrPaint color will be ignored.

            GrColor4f shaderInput = origColor.opaque();
            shaderFP = GrFragmentProcessor::OverrideInput(std::move(shaderFP), shaderInput);
            shaderFP = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(shaderFP),
                                                                         *primColorMode);

            // The above may return null if compose results in a pass through of the prim color.
            if (shaderFP) {
                grPaint->addColorFragmentProcessor(std::move(shaderFP));
            }

            // We can ignore origColor here - alpha is unchanged by gamma
            GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
            if (GrColor_WHITE != paintAlpha) {
                // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
                // color channels. It's value should be treated as the same in ANY color space.
                grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
                    GrColor4f::FromGrColor(paintAlpha),
                    GrConstColorProcessor::InputMode::kModulateRGBA));
            }
        } else {
            // The shader's FP sees the paint unpremul color
            grPaint->setColor4f(origColor);
            grPaint->addColorFragmentProcessor(std::move(shaderFP));
        }
    } else {
        if (primColorMode) {
            // There is a blend between the primitive color and the paint color. The blend considers
            // the opaque paint color. The paint's alpha is applied to the post-blended color.
            auto processor = GrConstColorProcessor::Make(origColor.opaque(),
                                                         GrConstColorProcessor::InputMode::kIgnore);
            processor = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(processor),
                                                                          *primColorMode);
            if (processor) {
                grPaint->addColorFragmentProcessor(std::move(processor));
            }

            grPaint->setColor4f(origColor.opaque());

            // We can ignore origColor here - alpha is unchanged by gamma
            GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
            if (GrColor_WHITE != paintAlpha) {
                // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
                // color channels. It's value should be treated as the same in ANY color space.
                grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
                    GrColor4f::FromGrColor(paintAlpha),
                    GrConstColorProcessor::InputMode::kModulateRGBA));
            }
        } else {
            // No shader, no primitive color.
            grPaint->setColor4f(origColor.premul());
            applyColorFilterToPaintColor = true;
        }
    }

    SkColorFilter* colorFilter = skPaint.getColorFilter();
    if (colorFilter) {
        if (applyColorFilterToPaintColor) {
            // If we're in legacy mode, we *must* avoid using the 4f version of the color filter,
            // because that will combine with the linearized version of the stored color.
            if (colorSpaceInfo.isGammaCorrect()) {
                grPaint->setColor4f(GrColor4f::FromSkColor4f(
                    colorFilter->filterColor4f(origColor.toSkColor4f())).premul());
            } else {
                grPaint->setColor4f(SkColorToPremulGrColor4fLegacy(
                        colorFilter->filterColor(skPaint.getColor())));
            }
        } else {
            auto cfFP = colorFilter->asFragmentProcessor(context, colorSpaceInfo);
            if (cfFP) {
                grPaint->addColorFragmentProcessor(std::move(cfFP));
            } else {
                return false;
            }
        }
    }

    SkMaskFilterBase* maskFilter = as_MFB(skPaint.getMaskFilter());
    if (maskFilter) {
        if (auto mfFP = maskFilter->asFragmentProcessor(fpArgs)) {
            grPaint->addCoverageFragmentProcessor(std::move(mfFP));
        }
    }

    // When the xfermode is null on the SkPaint (meaning kSrcOver) we need the XPFactory field on
    // the GrPaint to also be null (also kSrcOver).
    SkASSERT(!grPaint->getXPFactory());
    if (!skPaint.isSrcOver()) {
        grPaint->setXPFactory(SkBlendMode_AsXPFactory(skPaint.getBlendMode()));
    }

#ifndef SK_IGNORE_GPU_DITHER
    // Conservative default, in case GrPixelConfigToColorType() fails.
    SkColorType ct = SkColorType::kRGB_565_SkColorType;
    GrPixelConfigToColorType(colorSpaceInfo.config(), &ct);
    if (SkPaintPriv::ShouldDither(skPaint, ct) && grPaint->numColorFragmentProcessors() > 0 &&
        !colorSpaceInfo.isGammaCorrect()) {
        auto ditherFP = GrDitherEffect::Make(colorSpaceInfo.config());
        if (ditherFP) {
            grPaint->addColorFragmentProcessor(std::move(ditherFP));
        }
    }
#endif
    return true;
}
Ejemplo n.º 4
0
void GrVkPipelineState::writeSamplers(GrVkGpu* gpu,
                                      const SkTArray<const GrTextureAccess*>& textureBindings) {
    SkASSERT(fNumSamplers == textureBindings.count());

    for (int i = 0; i < textureBindings.count(); ++i) {
        const GrTextureParams& params = textureBindings[i]->getParams();

        GrVkTexture* texture = static_cast<GrVkTexture*>(textureBindings[i]->getTexture());
        if (GrTextureParams::kMipMap_FilterMode == params.filterMode()) {
            if (texture->texturePriv().mipMapsAreDirty()) {
                gpu->generateMipmap(texture);
                texture->texturePriv().dirtyMipMaps(false);
            }
        }

        fSamplers.push(gpu->resourceProvider().findOrCreateCompatibleSampler(params,
                                                          texture->texturePriv().maxMipMapLevel()));

        const GrVkImage::Resource* textureResource = texture->resource();
        textureResource->ref();
        fTextures.push(textureResource);

        const GrVkImageView* textureView = texture->textureView();
        textureView->ref();
        fTextureViews.push(textureView);

        // Change texture layout so it can be read in shader
        VkImageLayout layout = texture->currentLayout();
        VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
        VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
        VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
        VkAccessFlags dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
        texture->setImageLayout(gpu,
                                VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
                                srcAccessMask,
                                dstAccessMask,
                                srcStageMask,
                                dstStageMask,
                                false);

        VkDescriptorImageInfo imageInfo;
        memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo));
        imageInfo.sampler = fSamplers[i]->sampler();
        imageInfo.imageView = texture->textureView()->imageView();
        imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;

        VkWriteDescriptorSet writeInfo;
        memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet));
        writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
        writeInfo.pNext = nullptr;
        writeInfo.dstSet = fDescriptorSets[GrVkUniformHandler::kSamplerDescSet];
        writeInfo.dstBinding = i;
        writeInfo.dstArrayElement = 0;
        writeInfo.descriptorCount = 1;
        writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
        writeInfo.pImageInfo = &imageInfo;
        writeInfo.pBufferInfo = nullptr;
        writeInfo.pTexelBufferView = nullptr;

        GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(),
                                                            1,
                                                            &writeInfo,
                                                            0,
                                                            nullptr));
    }
}
Ejemplo n.º 5
0
GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args,
                                 GrPipelineOptimizations* opts) {
    const GrPipelineBuilder& builder = *args.fPipelineBuilder;

    // Create XferProcessor from DS's XPFactory
    SkAutoTUnref<GrXferProcessor> xferProcessor(
        builder.getXPFactory()->createXferProcessor(args.fColorPOI, args.fCoveragePOI,
                builder.hasMixedSamples(), &args.fDstTexture,
                *args.fCaps));
    if (!xferProcessor) {
        return nullptr;
    }

    GrColor overrideColor = GrColor_ILLEGAL;
    if (args.fColorPOI.firstEffectiveProcessorIndex() != 0) {
        overrideColor = args.fColorPOI.inputColorToFirstEffectiveProccesor();
    }

    GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_OptFlags;

    optFlags = xferProcessor->getOptimizations(args.fColorPOI,
               args.fCoveragePOI,
               builder.getStencil().doesWrite(),
               &overrideColor,
               *args.fCaps);

    // When path rendering the stencil settings are not always set on the GrPipelineBuilder
    // so we must check the draw type. In cases where we will skip drawing we simply return a
    // null GrPipeline.
    if (GrXferProcessor::kSkipDraw_OptFlag & optFlags) {
        return nullptr;
    }

    // No need to have an override color if it isn't even going to be used.
    if (SkToBool(GrXferProcessor::kIgnoreColor_OptFlag & optFlags)) {
        overrideColor = GrColor_ILLEGAL;
    }

    GrPipeline* pipeline = new (memory) GrPipeline;
    pipeline->fXferProcessor.reset(xferProcessor.get());

    pipeline->fRenderTarget.reset(builder.fRenderTarget.get());
    SkASSERT(pipeline->fRenderTarget);
    pipeline->fScissorState = *args.fScissor;
    pipeline->fStencilSettings = builder.getStencil();
    pipeline->fDrawFace = builder.getDrawFace();

    pipeline->fFlags = 0;
    if (builder.isHWAntialias()) {
        pipeline->fFlags |= kHWAA_Flag;
    }
    if (builder.isDither()) {
        pipeline->fFlags |= kDither_Flag;
    }
    if (builder.snapVerticesToPixelCenters()) {
        pipeline->fFlags |= kSnapVertices_Flag;
    }

    int firstColorProcessorIdx = args.fColorPOI.firstEffectiveProcessorIndex();

    // TODO: Once we can handle single or four channel input into coverage GrFragmentProcessors
    // then we can use GrPipelineBuilder's coverageProcInfo (like color above) to set this initial
    // information.
    int firstCoverageProcessorIdx = 0;

    pipeline->adjustProgramFromOptimizations(builder, optFlags, args.fColorPOI, args.fCoveragePOI,
            &firstColorProcessorIdx, &firstCoverageProcessorIdx);

    bool usesLocalCoords = false;

    // Copy GrFragmentProcessors from GrPipelineBuilder to Pipeline
    pipeline->fNumColorProcessors = builder.numColorFragmentProcessors() - firstColorProcessorIdx;
    int numTotalProcessors = pipeline->fNumColorProcessors +
                             builder.numCoverageFragmentProcessors() - firstCoverageProcessorIdx;
    pipeline->fFragmentProcessors.reset(numTotalProcessors);
    int currFPIdx = 0;
    for (int i = firstColorProcessorIdx; i < builder.numColorFragmentProcessors();
            ++i, ++currFPIdx) {
        const GrFragmentProcessor* fp = builder.getColorFragmentProcessor(i);
        pipeline->fFragmentProcessors[currFPIdx].reset(fp);
        usesLocalCoords = usesLocalCoords || fp->usesLocalCoords();
        fp->gatherCoordTransforms(&pipeline->fCoordTransforms);
    }

    for (int i = firstCoverageProcessorIdx; i < builder.numCoverageFragmentProcessors();
            ++i, ++currFPIdx) {
        const GrFragmentProcessor* fp = builder.getCoverageFragmentProcessor(i);
        pipeline->fFragmentProcessors[currFPIdx].reset(fp);
        usesLocalCoords = usesLocalCoords || fp->usesLocalCoords();
        fp->gatherCoordTransforms(&pipeline->fCoordTransforms);
    }

    // Setup info we need to pass to GrPrimitiveProcessors that are used with this GrPipeline.
    opts->fFlags = 0;
    if (!SkToBool(optFlags & GrXferProcessor::kIgnoreColor_OptFlag)) {
        opts->fFlags |= GrPipelineOptimizations::kReadsColor_Flag;
    }
    if (GrColor_ILLEGAL != overrideColor) {
        opts->fFlags |= GrPipelineOptimizations::kUseOverrideColor_Flag;
        opts->fOverrideColor = overrideColor;
    }
    if (!SkToBool(optFlags & GrXferProcessor::kIgnoreCoverage_OptFlag)) {
        opts->fFlags |= GrPipelineOptimizations::kReadsCoverage_Flag;
    }
    if (usesLocalCoords) {
        opts->fFlags |= GrPipelineOptimizations::kReadsLocalCoords_Flag;
    }
    if (SkToBool(optFlags & GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag)) {
        opts->fFlags |= GrPipelineOptimizations::kCanTweakAlphaForCoverage_Flag;
    }

    GrXPFactory::InvariantBlendedColor blendedColor;
    builder.fXPFactory->getInvariantBlendedColor(args.fColorPOI, &blendedColor);
    if (blendedColor.fWillBlendWithDst) {
        opts->fFlags |= GrPipelineOptimizations::kWillColorBlendWithDst_Flag;
    }

    return pipeline;
}
Ejemplo n.º 6
0
bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
                             int startIndex, int vertexCount,
                             int indexCount) const {
    const GrDrawState& drawState = this->getDrawState();
#ifdef SK_DEBUG
    const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    int maxVertex = startVertex + vertexCount;
    int maxValidVertex;
    switch (geoSrc.fVertexSrc) {
        case kNone_GeometrySrcType:
            SkFAIL("Attempting to draw without vertex src.");
        case kReserved_GeometrySrcType: // fallthrough
        case kArray_GeometrySrcType:
            maxValidVertex = geoSrc.fVertexCount;
            break;
        case kBuffer_GeometrySrcType:
            maxValidVertex = static_cast<int>(geoSrc.fVertexBuffer->gpuMemorySize() / geoSrc.fVertexSize);
            break;
    }
    if (maxVertex > maxValidVertex) {
        SkFAIL("Drawing outside valid vertex range.");
    }
    if (indexCount > 0) {
        int maxIndex = startIndex + indexCount;
        int maxValidIndex;
        switch (geoSrc.fIndexSrc) {
            case kNone_GeometrySrcType:
                SkFAIL("Attempting to draw indexed geom without index src.");
            case kReserved_GeometrySrcType: // fallthrough
            case kArray_GeometrySrcType:
                maxValidIndex = geoSrc.fIndexCount;
                break;
            case kBuffer_GeometrySrcType:
                maxValidIndex = static_cast<int>(geoSrc.fIndexBuffer->gpuMemorySize() / sizeof(uint16_t));
                break;
        }
        if (maxIndex > maxValidIndex) {
            SkFAIL("Index reads outside valid index range.");
        }
    }

    SkASSERT(drawState.getRenderTarget());

    if (drawState.hasGeometryProcessor()) {
        const GrGeometryProcessor* gp = drawState.getGeometryProcessor()->getProcessor();
        int numTextures = gp->numTextures();
        for (int t = 0; t < numTextures; ++t) {
            GrTexture* texture = gp->texture(t);
            SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget());
        }
    }

    for (int s = 0; s < drawState.numColorStages(); ++s) {
        const GrProcessor* effect = drawState.getColorStage(s).getProcessor();
        int numTextures = effect->numTextures();
        for (int t = 0; t < numTextures; ++t) {
            GrTexture* texture = effect->texture(t);
            SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget());
        }
    }
    for (int s = 0; s < drawState.numCoverageStages(); ++s) {
        const GrProcessor* effect = drawState.getCoverageStage(s).getProcessor();
        int numTextures = effect->numTextures();
        for (int t = 0; t < numTextures; ++t) {
            GrTexture* texture = effect->texture(t);
            SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget());
        }
    }

    SkASSERT(drawState.validateVertexAttribs());
#endif
    if (NULL == drawState.getRenderTarget()) {
        return false;
    }
    return true;
}
Ejemplo n.º 7
0
void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) {
    SkASSERT(this->isIndexed());
    fStartIndex += indexOffset;
    SkASSERT(fStartIndex >= 0);
}
Ejemplo n.º 8
0
// Test out the non-degenerate RR cases
static void test_round_rect_general(skiatest::Reporter* reporter) {
    static const SkScalar kEps = 0.1f;
    static const SkScalar kDist20 = 20 * (SK_Scalar1 - SK_ScalarRoot2Over2);
    static const SkPoint pts[] = {
        // Upper Left
        { kDist20 - kEps, kDist20 - kEps },       // out
        { kDist20 + kEps, kDist20 + kEps },       // in
        // Upper Right
        { kWidth + kEps - kDist20, kDist20 - kEps },     // out
        { kWidth - kEps - kDist20, kDist20 + kEps },      // in
        // Lower Right
        { kWidth + kEps - kDist20, kHeight + kEps - kDist20 },   // out
        { kWidth - kEps - kDist20, kHeight - kEps - kDist20 },   // in
        // Lower Left
        { kDist20 - kEps, kHeight + kEps - kDist20 },     //out
        { kDist20 + kEps, kHeight - kEps - kDist20 },     // in
        // Middle
        { SkIntToScalar(50), SkIntToScalar(50) } // in
    };
    static const bool isIn[] = { false, true, false, true, false, true, false, true, true };

    SkASSERT(SK_ARRAY_COUNT(pts) == SK_ARRAY_COUNT(isIn));

    //----
    SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
    SkRRect rr1;
    rr1.setRectXY(rect, 20, 20);

    REPORTER_ASSERT(reporter, SkRRect::kSimple_Type == rr1.type());
    for (size_t i = 0; i < SK_ARRAY_COUNT(pts); ++i) {
        REPORTER_ASSERT(reporter, isIn[i] == rr1.contains(pts[i].fX, pts[i].fY));
    }

    //----
    static const SkScalar kDist50 = 50*(SK_Scalar1 - SK_ScalarRoot2Over2);
    static const SkPoint pts2[] = {
        // Upper Left
        { -SK_Scalar1, -SK_Scalar1 },           // out
        { SK_Scalar1, SK_Scalar1 },             // in
        // Upper Right
        { kWidth + kEps - kDist20, kDist20 - kEps },     // out
        { kWidth - kEps - kDist20, kDist20 + kEps },     // in
        // Lower Right
        { kWidth + kEps - kDist50, kHeight + kEps - kDist50 },   // out
        { kWidth - kEps - kDist50, kHeight - kEps - kDist50 },   // in
        // Lower Left
        { kDist20 - kEps, kHeight + kEps - kDist50 },     // out
        { kDist20 + kEps, kHeight - kEps - kDist50 },     // in
        // Middle
        { SkIntToScalar(50), SkIntToScalar(50) }  // in
    };

    SkASSERT(SK_ARRAY_COUNT(pts2) == SK_ARRAY_COUNT(isIn));

    SkPoint radii[4] = { { 0, 0 }, { 20, 20 }, { 50, 50 }, { 20, 50 } };

    SkRRect rr2;
    rr2.setRectRadii(rect, radii);

    REPORTER_ASSERT(reporter, SkRRect::kComplex_Type == rr2.type());
    for (size_t i = 0; i < SK_ARRAY_COUNT(pts); ++i) {
        REPORTER_ASSERT(reporter, isIn[i] == rr2.contains(pts2[i].fX, pts2[i].fY));
    }
}
Ejemplo n.º 9
0
size_t SkPDFStream::dataSize() const {
    SkASSERT(fDataStream->hasLength());
    return fDataStream->getLength();
}
Ejemplo n.º 10
0
bool NativeInputWindowHandle::updateInfo()
{
    AutoPtr<IInputWindowHandle> obj;
    mObjWeak->Resolve(EIID_IInputWindowHandle, (IInterface**)&obj);
    if (!obj) {
        releaseInfo();
        return false;
    }

    if (!mInfo) {
        mInfo = new android::InputWindowInfo();
    }
    else {
        mInfo->touchableRegion.clear();
    }

    Elastos::Droid::Server::Input::InputWindowHandle* handle =
            (Elastos::Droid::Server::Input::InputWindowHandle*)obj.Get();
    AutoPtr<IInputChannel> inputChannelObj = handle->mInputChannel;
    if (inputChannelObj) {
        Handle64 ptr;
        inputChannelObj->GetNativeInputChannel(&ptr);
        NativeInputChannel* nativeInputChannel = reinterpret_cast<NativeInputChannel*>(ptr);
        mInfo->inputChannel = nativeInputChannel != NULL ? nativeInputChannel->getInputChannel() : NULL;
    }
    else {
        mInfo->inputChannel.clear();
    }

    if (!handle->mName.IsNull()) {
        mInfo->name.setTo(handle->mName.string());
    }
    else {
        mInfo->name.setTo("<null>");
    }

    mInfo->layoutParamsFlags = handle->mLayoutParamsFlags;
    mInfo->layoutParamsType = handle->mLayoutParamsType;
    mInfo->dispatchingTimeout = handle->mDispatchingTimeoutNanos;
    mInfo->frameLeft = handle->mFrameLeft;
    mInfo->frameTop = handle->mFrameTop;
    mInfo->frameRight = handle->mFrameRight;
    mInfo->frameBottom = handle->mFrameBottom;
    mInfo->scaleFactor = handle->mScaleFactor;

    AutoPtr<IRegion> regionObj = handle->mTouchableRegion;
    if (regionObj) {
        Int64 regionHandle;
        regionObj->GetNativeRegion((Handle64*)&regionHandle);
        SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
        SkASSERT(region != NULL);

        for (SkRegion::Iterator it(*region); !it.done(); it.next()) {
            const SkIRect& rect = it.rect();
            mInfo->addTouchableRegion(android::Rect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom));
        }
    }

    mInfo->visible = handle->mVisible;
    mInfo->canReceiveKeys = handle->mCanReceiveKeys;
    mInfo->hasFocus = handle->mHasFocus;
    mInfo->hasWallpaper = handle->mHasWallpaper;
    mInfo->paused = handle->mPaused;
    mInfo->layer = handle->mLayer;
    mInfo->ownerPid = handle->mOwnerPid;
    mInfo->ownerUid = handle->mOwnerUid;
    mInfo->inputFeatures = handle->mInputFeatures;
    mInfo->displayId = handle->mDisplayId;

    return true;
}
Ejemplo n.º 11
0
// Test out the cases when the RR degenerates to a rect
static void test_round_rect_rects(skiatest::Reporter* reporter) {
    SkRect r;
    static const SkPoint pts[] = {
        // Upper Left
        { -SK_Scalar1, -SK_Scalar1 },               // out
        { SK_Scalar1, SK_Scalar1 },                 // in
        // Upper Right
        { SkIntToScalar(101), -SK_Scalar1},         // out
        { SkIntToScalar(99), SK_Scalar1 },          // in
        // Lower Right
        { SkIntToScalar(101), SkIntToScalar(101) }, // out
        { SkIntToScalar(99), SkIntToScalar(99) },   // in
        // Lower Left
        { -SK_Scalar1, SkIntToScalar(101) },        // out
        { SK_Scalar1, SkIntToScalar(99) },          // in
        // Middle
        { SkIntToScalar(50), SkIntToScalar(50) }    // in
    };
    static const bool isIn[] = { false, true, false, true, false, true, false, true, true };

    SkASSERT(SK_ARRAY_COUNT(pts) == SK_ARRAY_COUNT(isIn));

    //----
    SkRRect empty;

    empty.setEmpty();

    REPORTER_ASSERT(reporter, SkRRect::kEmpty_Type == empty.type());
    r = empty.rect();
    REPORTER_ASSERT(reporter, 0 == r.fLeft && 0 == r.fTop && 0 == r.fRight && 0 == r.fBottom);

    //----
    SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
    SkRRect rr1;
    rr1.setRectXY(rect, 0, 0);

    REPORTER_ASSERT(reporter, SkRRect::kRect_Type == rr1.type());
    r = rr1.rect();
    REPORTER_ASSERT(reporter, rect == r);
    for (size_t i = 0; i < SK_ARRAY_COUNT(pts); ++i) {
        REPORTER_ASSERT(reporter, isIn[i] == rr1.contains(pts[i].fX, pts[i].fY));
    }

    //----
    SkPoint radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };

    SkRRect rr2;
    rr2.setRectRadii(rect, radii);

    REPORTER_ASSERT(reporter, SkRRect::kRect_Type == rr2.type());
    r = rr2.rect();
    REPORTER_ASSERT(reporter, rect == r);
    for (size_t i = 0; i < SK_ARRAY_COUNT(pts); ++i) {
        REPORTER_ASSERT(reporter, isIn[i] == rr2.contains(pts[i].fX, pts[i].fY));
    }

    //----
    SkPoint radii2[4] = { { 0, 0 }, { 20, 20 }, { 50, 50 }, { 20, 50 } };

    SkRRect rr3;
    rr3.setRectRadii(rect, radii2);
    REPORTER_ASSERT(reporter, SkRRect::kComplex_Type == rr3.type());
}
Ejemplo n.º 12
0
 ~AutoCachePurge() {
     SkASSERT(fXformer->fReentryCount > 0);
     if (--fXformer->fReentryCount == 0) {
         fXformer->purgeCaches();
     }
 }
 SkTypeface* createTypeface(int index) override { SkASSERT(false); return nullptr; }
 void getStyle(int index, SkFontStyle*, SkString* style) override { SkASSERT(false); }
Ejemplo n.º 15
0
void GrResourceEntry::validate() const {
    SkASSERT(fResource);
    SkASSERT(fResource->getCacheEntry() == this);
    fResource->validate();
}
Ejemplo n.º 16
0
SkDrawTo::~SkDrawTo() {
    SkASSERT(0);
}
Ejemplo n.º 17
0
SkString GrDrawTargetCaps::dump() const {
    SkString r;
    static const char* gNY[] = {"NO", "YES"};
    r.appendf("MIP Map Support              : %s\n", gNY[fMipMapSupport]);
    r.appendf("NPOT Texture Tile Support    : %s\n", gNY[fNPOTTextureTileSupport]);
    r.appendf("Two Sided Stencil Support    : %s\n", gNY[fTwoSidedStencilSupport]);
    r.appendf("Stencil Wrap Ops  Support    : %s\n", gNY[fStencilWrapOpsSupport]);
    r.appendf("HW AA Lines Support          : %s\n", gNY[fHWAALineSupport]);
    r.appendf("Shader Derivative Support    : %s\n", gNY[fShaderDerivativeSupport]);
    r.appendf("Geometry Shader Support      : %s\n", gNY[fGeometryShaderSupport]);
    r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]);
    r.appendf("Path Rendering Support       : %s\n", gNY[fPathRenderingSupport]);
    r.appendf("Dst Read In Shader Support   : %s\n", gNY[fDstReadInShaderSupport]);
    r.appendf("Discard Render Target Support: %s\n", gNY[fDiscardRenderTargetSupport]);
    r.appendf("Reuse Scratch Textures       : %s\n", gNY[fReuseScratchTextures]);
    r.appendf("Gpu Tracing Support          : %s\n", gNY[fGpuTracingSupport]);
    r.appendf("Compressed Update Support    : %s\n", gNY[fCompressedTexSubImageSupport]);
    r.appendf("Max Texture Size             : %d\n", fMaxTextureSize);
    r.appendf("Max Render Target Size       : %d\n", fMaxRenderTargetSize);
    r.appendf("Max Sample Count             : %d\n", fMaxSampleCount);

    r.appendf("Map Buffer Support           : %s\n", map_flags_to_string(fMapBufferFlags).c_str());

    static const char* kConfigNames[] = {
        "Unknown",  // kUnknown_GrPixelConfig
        "Alpha8",   // kAlpha_8_GrPixelConfig,
        "Index8",   // kIndex_8_GrPixelConfig,
        "RGB565",   // kRGB_565_GrPixelConfig,
        "RGBA444",  // kRGBA_4444_GrPixelConfig,
        "RGBA8888", // kRGBA_8888_GrPixelConfig,
        "BGRA8888", // kBGRA_8888_GrPixelConfig,
        "ETC1",     // kETC1_GrPixelConfig,
        "LATC",     // kLATC_GrPixelConfig,
        "R11EAC",   // kR11_EAC_GrPixelConfig,
        "ASTC12x12",// kASTC_12x12_GrPixelConfig,
        "RGBAFloat",  // kRGBA_float_GrPixelConfig
    };
    GR_STATIC_ASSERT(0  == kUnknown_GrPixelConfig);
    GR_STATIC_ASSERT(1  == kAlpha_8_GrPixelConfig);
    GR_STATIC_ASSERT(2  == kIndex_8_GrPixelConfig);
    GR_STATIC_ASSERT(3  == kRGB_565_GrPixelConfig);
    GR_STATIC_ASSERT(4  == kRGBA_4444_GrPixelConfig);
    GR_STATIC_ASSERT(5  == kRGBA_8888_GrPixelConfig);
    GR_STATIC_ASSERT(6  == kBGRA_8888_GrPixelConfig);
    GR_STATIC_ASSERT(7  == kETC1_GrPixelConfig);
    GR_STATIC_ASSERT(8  == kLATC_GrPixelConfig);
    GR_STATIC_ASSERT(9  == kR11_EAC_GrPixelConfig);
    GR_STATIC_ASSERT(10 == kASTC_12x12_GrPixelConfig);
    GR_STATIC_ASSERT(11 == kRGBA_float_GrPixelConfig);
    GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt);

    SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]);
    SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][1]);

    for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i)  {
        r.appendf("%s is renderable: %s, with MSAA: %s\n",
                  kConfigNames[i],
                  gNY[fConfigRenderSupport[i][0]],
                  gNY[fConfigRenderSupport[i][1]]);
    }

    SkASSERT(!fConfigTextureSupport[kUnknown_GrPixelConfig]);

    for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i)  {
        r.appendf("%s is uploadable to a texture: %s\n",
                  kConfigNames[i],
                  gNY[fConfigTextureSupport[i]]);
    }

    return r;
}
Ejemplo n.º 18
0
const SkDisplayEnumMap& SkAnimatorScript::GetEnumValues(SkDisplayTypes type) {
    int index = SkTSearch<SkDisplayTypes>(&gEnumMaps[0].fType, gEnumMapCount, type,
        sizeof(SkDisplayEnumMap));
    SkASSERT(index >= 0);
    return gEnumMaps[index];
}
Ejemplo n.º 19
0
void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) {
    fStartVertex += vertexOffset;
    SkASSERT(fStartVertex >= 0);
}
Ejemplo n.º 20
0
DEF_TEST(SkpSkGr, reporter) {
    SkTArray<TestResult, true> errors;
    if (!initTest()) {
        return;
    }
    SkpSkGrThreadState state;
    state.init(0);
    int smallCount = 0;
    for (int dirNo = 1; dirNo <= 100; ++dirNo) {
        SkString pictDir = make_in_dir_name(dirNo);
        SkASSERT(pictDir.size());
        if (reporter->verbose()) {
            SkDebugf("dirNo=%d\n", dirNo);
        }
        SkOSFile::Iter iter(pictDir.c_str(), "skp");
        SkString filename;
        int testCount = 0;
        PreParser preParser(dirNo);
        SkFILEWStream statusStream(makeStatusString(dirNo).c_str());
        while (iter.next(&filename)) {
            for (size_t index = 0; index < skipOverSkGrCount; ++index) {
                if (skipOverSkGr[index].directory == dirNo
                        && strcmp(filename.c_str(), skipOverSkGr[index].filename) == 0) {
                    goto skipOver;
                }
            }
            if (preParser.match(filename, &statusStream, &state.fResult)) {
                addError(&state);
                ++testCount;
                goto checkEarlyExit;
            }
            if (state.fSmallestError > 5000000) {
                goto breakOut;
            }
            {
                TestResult& result = state.fResult;
                result.test(dirNo, filename);
                SkString outStr(result.status());
                statusStream.write(outStr.c_str(), outStr.size());
                statusStream.flush();
                if (1) {
                    SkDebugf("%s", outStr.c_str());
                }
                bool noMatch = addError(&state);
                if (noMatch) {
                    smallCount = 0;
                } else if (++smallCount > 10000) {
                    goto breakOut;
                }
            }
            ++testCount;
            if (reporter->verbose()) {
                if (testCount % 100 == 0) {
                    SkDebugf("#%d\n", testCount);
                }
            }
     skipOver:
             reporter->bumpTestCount();
    checkEarlyExit:
            if (1 && testCount == 20) {
                break;
            }
        }
    }
breakOut:
    if (reporter->verbose()) {
        for (int index = 0; index < state.fFoundCount; ++index) {
            SkDebugf("%d %s %d\n", state.fDirsFound[index], state.fFilesFound[index],
                     state.fError[index]);
        }
    }
    for (int index = 0; index < state.fFoundCount; ++index) {
        TestResult::Test(state.fDirsFound[index], state.fFilesFound[index], kEncodeFiles,
                reporter->verbose());
        if (reporter->verbose()) SkDebugf("+");
    }
}
Ejemplo n.º 21
0
static SkTypeface::Encoding paint2encoding(const SkPaint& paint) {
    SkPaint::TextEncoding enc = paint.getTextEncoding();
    SkASSERT(SkPaint::kGlyphID_TextEncoding != enc);
    return (SkTypeface::Encoding)enc;
}
Ejemplo n.º 22
0
void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) {
    SkASSERT(bm.width() == fBitmap.width());
    SkASSERT(bm.height() == fBitmap.height());
    fBitmap = bm;   // intent is to use bm's pixelRef (and rowbytes/config)
    fBitmap.lockPixels();
}
Ejemplo n.º 23
0
GrTexture* GaussianBlur(GrContext* context,
                        GrTexture* srcTexture,
                        bool canClobberSrc,
                        const SkRect& rect,
                        bool cropToRect,
                        float sigmaX,
                        float sigmaY) {
    SkASSERT(NULL != context);

    GrContext::AutoRenderTarget art(context);

    GrContext::AutoMatrix am;
    am.setIdentity(context);

    SkIRect clearRect;
    int scaleFactorX, radiusX;
    int scaleFactorY, radiusY;
    sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX);
    sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY);

    SkRect srcRect(rect);
    scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
    srcRect.roundOut();
    scale_rect(&srcRect, static_cast<float>(scaleFactorX),
                         static_cast<float>(scaleFactorY));

    GrContext::AutoClip acs(context, SkRect::MakeWH(srcRect.width(), srcRect.height()));

    SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
             kRGBA_8888_GrPixelConfig == srcTexture->config() ||
             kAlpha_8_GrPixelConfig == srcTexture->config());

    GrTextureDesc desc;
    desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
    desc.fWidth = SkScalarFloorToInt(srcRect.width());
    desc.fHeight = SkScalarFloorToInt(srcRect.height());
    desc.fConfig = srcTexture->config();

    GrAutoScratchTexture temp1, temp2;
    GrTexture* dstTexture = temp1.set(context, desc);
    GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(context, desc);
    if (NULL == dstTexture || NULL == tempTexture) {
        return NULL;
    }

    for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
        GrPaint paint;
        SkMatrix matrix;
        matrix.setIDiv(srcTexture->width(), srcTexture->height());
        context->setRenderTarget(dstTexture->asRenderTarget());
        SkRect dstRect(srcRect);
        if (cropToRect && i == 1) {
            dstRect.offset(-dstRect.fLeft, -dstRect.fTop);
            SkRect domain;
            matrix.mapRect(&domain, rect);
            domain.inset(i < scaleFactorX ? SK_ScalarHalf / srcTexture->width() : 0.0f,
                         i < scaleFactorY ? SK_ScalarHalf / srcTexture->height() : 0.0f);
            SkAutoTUnref<GrEffectRef> effect(GrTextureDomainEffect::Create(
                srcTexture,
                matrix,
                domain,
                GrTextureDomain::kDecal_Mode,
                GrTextureParams::kBilerp_FilterMode));
            paint.addColorEffect(effect);
        } else {
            GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
            paint.addColorTextureEffect(srcTexture, matrix, params);
        }
        scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
                             i < scaleFactorY ? 0.5f : 1.0f);
        context->drawRectToRect(paint, dstRect, srcRect);
        srcRect = dstRect;
        srcTexture = dstTexture;
        SkTSwap(dstTexture, tempTexture);
    }

    SkIRect srcIRect;
    srcRect.roundOut(&srcIRect);

    if (sigmaX > 0.0f) {
        if (scaleFactorX > 1) {
            // Clear out a radius to the right of the srcRect to prevent the
            // X convolution from reading garbage.
            clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
                                          radiusX, srcIRect.height());
            context->clear(&clearRect, 0x0, false);
        }
        context->setRenderTarget(dstTexture->asRenderTarget());
        SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
        convolve_gaussian(context, srcRect, dstRect, srcTexture,
                          Gr1DKernelEffect::kX_Direction, radiusX, sigmaX, cropToRect);
        srcTexture = dstTexture;
        srcRect = dstRect;
        SkTSwap(dstTexture, tempTexture);
    }

    if (sigmaY > 0.0f) {
        if (scaleFactorY > 1 || sigmaX > 0.0f) {
            // Clear out a radius below the srcRect to prevent the Y
            // convolution from reading garbage.
            clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
                                          srcIRect.width(), radiusY);
            context->clear(&clearRect, 0x0, false);
        }

        context->setRenderTarget(dstTexture->asRenderTarget());
        SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
        convolve_gaussian(context, srcRect, dstRect, srcTexture,
                          Gr1DKernelEffect::kY_Direction, radiusY, sigmaY, cropToRect);
        srcTexture = dstTexture;
        srcRect = dstRect;
        SkTSwap(dstTexture, tempTexture);
    }

    if (scaleFactorX > 1 || scaleFactorY > 1) {
        // Clear one pixel to the right and below, to accommodate bilinear
        // upsampling.
        clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
                                      srcIRect.width() + 1, 1);
        context->clear(&clearRect, 0x0, false);
        clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
                                      1, srcIRect.height());
        context->clear(&clearRect, 0x0, false);
        SkMatrix matrix;
        matrix.setIDiv(srcTexture->width(), srcTexture->height());
        context->setRenderTarget(dstTexture->asRenderTarget());

        GrPaint paint;
        // FIXME:  this should be mitchell, not bilinear.
        GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
        paint.addColorTextureEffect(srcTexture, matrix, params);

        SkRect dstRect(srcRect);
        scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
        context->drawRectToRect(paint, dstRect, srcRect);
        srcRect = dstRect;
        srcTexture = dstTexture;
        SkTSwap(dstTexture, tempTexture);
    }
    if (srcTexture == temp1.texture()) {
        return temp1.detach();
    } else if (srcTexture == temp2.texture()) {
        return temp2.detach();
    } else {
        srcTexture->ref();
        return srcTexture;
    }
}
Ejemplo n.º 24
0
SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap) : fBitmap(bitmap) {
    SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL));
}
Ejemplo n.º 25
0
void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
                      const GlyphBuffer& glyphBuffer,  int from, int numGlyphs,
                      const FloatPoint& point) const {
    SkASSERT(sizeof(GlyphBufferGlyph) == sizeof(uint16_t)); // compile-time assert

    const GlyphBufferGlyph* glyphs = glyphBuffer.glyphs(from);
    SkScalar x = SkFloatToScalar(point.x());
    SkScalar y = SkFloatToScalar(point.y());

    // FIXME: text rendering speed:
    // Android has code in their WebCore fork to special case when the
    // GlyphBuffer has no advances other than the defaults. In that case the
    // text drawing can proceed faster. However, it's unclear when those
    // patches may be upstreamed to WebKit so we always use the slower path
    // here.
    const GlyphBufferAdvance* adv = glyphBuffer.advances(from);
    SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
    SkPoint* pos = storage.get();

    for (int i = 0; i < numGlyphs; i++) {
        pos[i].set(x, y);
        x += SkFloatToScalar(adv[i].width());
        y += SkFloatToScalar(adv[i].height());
    }

    gc->platformContext()->prepareForSoftwareDraw();

    SkCanvas* canvas = gc->platformContext()->canvas();
    int textMode = gc->platformContext()->getTextDrawingMode();

    // We draw text up to two times (once for fill, once for stroke).
    if (textMode & cTextFill) {
        SkPaint paint;
        gc->platformContext()->setupPaintForFilling(&paint);
        font->platformData().setupPaint(&paint);
        adjustTextRenderMode(&paint, gc->platformContext());
        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
        paint.setColor(gc->fillColor().rgb());
        canvas->drawPosText(glyphs, numGlyphs << 1, pos, paint);
    }

    if ((textMode & cTextStroke)
        && gc->platformContext()->getStrokeStyle() != NoStroke
        && gc->platformContext()->getStrokeThickness() > 0) {

        SkPaint paint;
        gc->platformContext()->setupPaintForStroking(&paint, 0, 0);
        font->platformData().setupPaint(&paint);
        adjustTextRenderMode(&paint, gc->platformContext());
        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
        paint.setColor(gc->strokeColor().rgb());

        if (textMode & cTextFill) {
            // If we also filled, we don't want to draw shadows twice.
            // See comment in FontChromiumWin.cpp::paintSkiaText() for more details.
            paint.setLooper(0)->safeUnref();
        }

        canvas->drawPosText(glyphs, numGlyphs << 1, pos, paint);
    }
}
Ejemplo n.º 26
0
SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties)
    : SkBaseDevice(deviceProperties)
    , fBitmap(bitmap)
{
    SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL));
}
Ejemplo n.º 27
0
void GrBitmapTextContext::flushGlyphs() {
    if (NULL == fDrawTarget) {
        return;
    }

    GrDrawState* drawState = fDrawTarget->drawState();
    GrDrawState::AutoRestoreEffects are(drawState);
    drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget());

    if (fCurrVertex > 0) {
        // setup our sampler state for our text texture/atlas
        SkASSERT(SkIsAlign4(fCurrVertex));
        GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode);

        GrTexture* currTexture = fStrike->getTexture();
        SkASSERT(currTexture);
        uint32_t textureUniqueID = currTexture->getUniqueID();
        
        if (textureUniqueID != fEffectTextureUniqueID) {
            fCachedEffect.reset(GrCustomCoordsTextureEffect::Create(currTexture, params));
            fEffectTextureUniqueID = textureUniqueID;
        }

        // This effect could be stored with one of the cache objects (atlas?)
        int coordsIdx = drawState->hasColorVertexAttribute() ? kGlyphCoordsWithColorAttributeIndex :
                                                               kGlyphCoordsNoColorAttributeIndex;
        drawState->addCoverageEffect(fCachedEffect.get(), coordsIdx);
        SkASSERT(NULL != fStrike);
        switch (fStrike->getMaskFormat()) {
            // Color bitmap text
            case kARGB_GrMaskFormat:
                SkASSERT(!drawState->hasColorVertexAttribute());
                drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
                drawState->setColor(0xffffffff);
                break;
            // LCD text
            case kA888_GrMaskFormat:
            case kA565_GrMaskFormat: {
                if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
                    kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
                    fPaint.numColorStages()) {
                    GrPrintf("LCD Text will not draw correctly.\n");
                }
                SkASSERT(!drawState->hasColorVertexAttribute());
                // We don't use the GrPaint's color in this case because it's been premultiplied by
                // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
                // the mask texture color. The end result is that we get
                //            mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
                int a = SkColorGetA(fSkPaint.getColor());
                // paintAlpha
                drawState->setColor(SkColorSetARGB(a, a, a, a));
                // paintColor
                drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor()));
                drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
                break;
            }
            // Grayscale/BW text
            case kA8_GrMaskFormat:
                // set back to normal in case we took LCD path previously.
                drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
                //drawState->setColor(fPaint.getColor());
                // We're using per-vertex color.
                SkASSERT(drawState->hasColorVertexAttribute());
                drawState->setColor(0xFFFFFFFF);
                break;
            default:
                SkFAIL("Unexepected mask format.");
        }
        int nGlyphs = fCurrVertex / 4;
        fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
        fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
                                          nGlyphs,
                                          4, 6, &fVertexBounds);

        fCurrVertex = 0;
        fVertexBounds.setLargestInverted();
    }

    fDrawTarget->resetVertexSource();
    fVertices = NULL;
}
Ejemplo n.º 28
0
GrResourceEntry::GrResourceEntry(const GrResourceKey& key, GrResource* resource)
        : fKey(key), fResource(resource) {
    // we assume ownership of the resource, and will unref it when we die
    SkASSERT(resource);
    resource->ref();
}
Ejemplo n.º 29
0
void GrResourceCache::validate() const {
    fList.validate();
    fExclusiveList.validate();
    SkASSERT(both_zero_or_nonzero(fEntryCount, fEntryBytes));
    SkASSERT(both_zero_or_nonzero(fClientDetachedCount, fClientDetachedBytes));
    SkASSERT(fClientDetachedBytes <= fEntryBytes);
    SkASSERT(fClientDetachedCount <= fEntryCount);
    SkASSERT((fEntryCount - fClientDetachedCount) == fCache.count());

    EntryList::Iter iter;

    // check that the exclusively held entries are okay
    const GrResourceCacheEntry* entry = iter.init(const_cast<EntryList&>(fExclusiveList),
                                                  EntryList::Iter::kHead_IterStart);

    for ( ; NULL != entry; entry = iter.next()) {
        entry->validate();
    }

    // check that the shareable entries are okay
    entry = iter.init(const_cast<EntryList&>(fList), EntryList::Iter::kHead_IterStart);

    int count = 0;
    for ( ; NULL != entry; entry = iter.next()) {
        entry->validate();
        SkASSERT(fCache.find(entry->key()));
        count += 1;
    }
    SkASSERT(count == fEntryCount - fClientDetachedCount);

    size_t bytes = countBytes(fList);
    SkASSERT(bytes == fEntryBytes  - fClientDetachedBytes);

    bytes = countBytes(fExclusiveList);
    SkASSERT(bytes == fClientDetachedBytes);

    SkASSERT(fList.countEntries() == fEntryCount - fClientDetachedCount);

    SkASSERT(fExclusiveList.countEntries() == fClientDetachedCount);
}
Ejemplo n.º 30
0
bool BGRAConvolve2D(const unsigned char* sourceData,
                    int sourceByteRowStride,
                    bool sourceHasAlpha,
                    const SkConvolutionFilter1D& filterX,
                    const SkConvolutionFilter1D& filterY,
                    int outputByteRowStride,
                    unsigned char* output,
                    const SkConvolutionProcs& convolveProcs,
                    bool useSimdIfPossible) {

    int maxYFilterSize = filterY.maxFilter();

    // The next row in the input that we will generate a horizontally
    // convolved row for. If the filter doesn't start at the beginning of the
    // image (this is the case when we are only resizing a subset), then we
    // don't want to generate any output rows before that. Compute the starting
    // row for convolution as the first pixel for the first vertical filter.
    int filterOffset, filterLength;
    const SkConvolutionFilter1D::ConvolutionFixed* filterValues =
        filterY.FilterForValue(0, &filterOffset, &filterLength);
    int nextXRow = filterOffset;

    // We loop over each row in the input doing a horizontal convolution. This
    // will result in a horizontally convolved image. We write the results into
    // a circular buffer of convolved rows and do vertical convolution as rows
    // are available. This prevents us from having to store the entire
    // intermediate image and helps cache coherency.
    // We will need four extra rows to allow horizontal convolution could be done
    // simultaneously. We also pad each row in row buffer to be aligned-up to
    // 16 bytes.
    // TODO(jiesun): We do not use aligned load from row buffer in vertical
    // convolution pass yet. Somehow Windows does not like it.
    int rowBufferWidth = (filterX.numValues() + 15) & ~0xF;
    int rowBufferHeight = maxYFilterSize +
                          (convolveProcs.fConvolve4RowsHorizontally ? 4 : 0);

    // check for too-big allocation requests : crbug.com/528628
    {
        int64_t size = sk_64_mul(rowBufferWidth, rowBufferHeight);
        // need some limit, to avoid over-committing success from malloc, but then
        // crashing when we try to actually use the memory.
        // 100meg seems big enough to allow "normal" zoom factors and image sizes through
        // while avoiding the crash seen by the bug (crbug.com/528628)
        if (size > 100 * 1024 * 1024) {
//            SkDebugf("BGRAConvolve2D: tmp allocation [%lld] too big\n", size);
            return false;
        }
    }

    CircularRowBuffer rowBuffer(rowBufferWidth,
                                rowBufferHeight,
                                filterOffset);

    // Loop over every possible output row, processing just enough horizontal
    // convolutions to run each subsequent vertical convolution.
    SkASSERT(outputByteRowStride >= filterX.numValues() * 4);
    int numOutputRows = filterY.numValues();

    // We need to check which is the last line to convolve before we advance 4
    // lines in one iteration.
    int lastFilterOffset, lastFilterLength;

    // SSE2 can access up to 3 extra pixels past the end of the
    // buffer. At the bottom of the image, we have to be careful
    // not to access data past the end of the buffer. Normally
    // we fall back to the C++ implementation for the last row.
    // If the last row is less than 3 pixels wide, we may have to fall
    // back to the C++ version for more rows. Compute how many
    // rows we need to avoid the SSE implementation for here.
    filterX.FilterForValue(filterX.numValues() - 1, &lastFilterOffset,
                           &lastFilterLength);
    int avoidSimdRows = 1 + convolveProcs.fExtraHorizontalReads /
                        (lastFilterOffset + lastFilterLength);

    filterY.FilterForValue(numOutputRows - 1, &lastFilterOffset,
                           &lastFilterLength);

    for (int outY = 0; outY < numOutputRows; outY++) {
        filterValues = filterY.FilterForValue(outY,
                                              &filterOffset, &filterLength);

        // Generate output rows until we have enough to run the current filter.
        while (nextXRow < filterOffset + filterLength) {
            if (convolveProcs.fConvolve4RowsHorizontally &&
                    nextXRow + 3 < lastFilterOffset + lastFilterLength -
                    avoidSimdRows) {
                const unsigned char* src[4];
                unsigned char* outRow[4];
                for (int i = 0; i < 4; ++i) {
                    src[i] = &sourceData[(uint64_t)(nextXRow + i) * sourceByteRowStride];
                    outRow[i] = rowBuffer.advanceRow();
                }
                convolveProcs.fConvolve4RowsHorizontally(src, filterX, outRow, 4*rowBufferWidth);
                nextXRow += 4;
            } else {
                // Check if we need to avoid SSE2 for this row.
                if (convolveProcs.fConvolveHorizontally &&
                        nextXRow < lastFilterOffset + lastFilterLength -
                        avoidSimdRows) {
                    convolveProcs.fConvolveHorizontally(
                        &sourceData[(uint64_t)nextXRow * sourceByteRowStride],
                        filterX, rowBuffer.advanceRow(), sourceHasAlpha);
                } else {
                    if (sourceHasAlpha) {
                        ConvolveHorizontallyAlpha(
                            &sourceData[(uint64_t)nextXRow * sourceByteRowStride],
                            filterX, rowBuffer.advanceRow());
                    } else {
                        ConvolveHorizontallyNoAlpha(
                            &sourceData[(uint64_t)nextXRow * sourceByteRowStride],
                            filterX, rowBuffer.advanceRow());
                    }
                }
                nextXRow++;
            }
        }

        // Compute where in the output image this row of final data will go.
        unsigned char* curOutputRow = &output[(uint64_t)outY * outputByteRowStride];

        // Get the list of rows that the circular buffer has, in order.
        int firstRowInCircularBuffer;
        unsigned char* const* rowsToConvolve =
            rowBuffer.GetRowAddresses(&firstRowInCircularBuffer);

        // Now compute the start of the subset of those rows that the filter
        // needs.
        unsigned char* const* firstRowForFilter =
            &rowsToConvolve[filterOffset - firstRowInCircularBuffer];

        if (convolveProcs.fConvolveVertically) {
            convolveProcs.fConvolveVertically(filterValues, filterLength,
                                              firstRowForFilter,
                                              filterX.numValues(), curOutputRow,
                                              sourceHasAlpha);
        } else {
            ConvolveVertically(filterValues, filterLength,
                               firstRowForFilter,
                               filterX.numValues(), curOutputRow,
                               sourceHasAlpha);
        }
    }
    return true;
}