Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d7448e65 authored by Chris Craik's avatar Chris Craik
Browse files

Add TextOnPath support to new reorderer/renderer

bug:22480459

Change-Id: I302048ec09901420c15003e21e44a551cc59c7ad
parent 20754c5a
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -705,6 +705,36 @@ void BakedOpDispatcher::onTextOp(BakedOpRenderer& renderer, const TextOp& op, co
    renderTextOp(renderer, op, state, clip, TextRenderType::Flush);
}

void BakedOpDispatcher::onTextOnPathOp(BakedOpRenderer& renderer, const TextOnPathOp& op, const BakedOpState& state) {
    // Note: can't trust clipSideFlags since we record with unmappedBounds == clip.
    // TODO: respect clipSideFlags, once we record with bounds
    const Rect* renderTargetClip = &state.computedState.clipRect;

    FontRenderer& fontRenderer = renderer.caches().fontRenderer.getFontRenderer();
    fontRenderer.setFont(op.paint, SkMatrix::I());
    fontRenderer.setTextureFiltering(true);

    Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);

    int alpha = PaintUtils::getAlphaDirect(op.paint) * state.alpha;
    SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(op.paint);
    TextDrawFunctor functor(&renderer, &state, renderTargetClip,
            0.0f, 0.0f, false, alpha, mode, op.paint);

    bool mustDirtyRenderTarget = renderer.offscreenRenderTarget();
    const Rect localSpaceClip = state.computedState.computeLocalSpaceClip();
    if (fontRenderer.renderTextOnPath(op.paint, &localSpaceClip,
            reinterpret_cast<const char*>(op.glyphs), op.glyphCount,
            op.path, op.hOffset, op.vOffset,
            mustDirtyRenderTarget ? &layerBounds : nullptr, &functor)) {
        if (mustDirtyRenderTarget) {
            // manually dirty render target, since TextDrawFunctor won't
            state.computedState.transform.mapRect(layerBounds);
            renderer.dirtyRenderTarget(layerBounds);
        }
    }
}

void BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op, const BakedOpState& state) {
    OffscreenBuffer* buffer = *op.layerHandle;

+9 −0
Original line number Diff line number Diff line
@@ -124,6 +124,15 @@ public:
        clipSideFlags = OpClipSideFlags::Full;
    }

    Rect computeLocalSpaceClip() const {
        Matrix4 inverse;
        inverse.loadInverse(transform);

        Rect outClip(clipRect);
        inverse.mapRect(outClip);
        return outClip;
    }

    Matrix4 transform;
    Rect clipRect;
    int clipSideFlags = 0;
+17 −13
Original line number Diff line number Diff line
@@ -90,7 +90,9 @@ public:
    }

    MergingOpBatch(batchid_t batchId, BakedOpState* op)
            : BatchBase(batchId, op, true) {
            : BatchBase(batchId, op, true)
            , mClipSideFlags(op->computedState.clipSideFlags)
            , mClipRect(op->computedState.clipRect) {
    }

    /*
@@ -202,11 +204,11 @@ public:
        if (newClipSideFlags & OpClipSideFlags::Bottom) mClipRect.bottom = opClip.bottom;
    }

    bool getClipSideFlags() const { return mClipSideFlags; }
    int getClipSideFlags() const { return mClipSideFlags; }
    const Rect& getClipRect() const { return mClipRect; }

private:
    int mClipSideFlags = 0;
    int mClipSideFlags;
    Rect mClipRect;
};

@@ -308,12 +310,6 @@ void OpReorderer::LayerReorderer::replayBakedOpsImpl(void* arg,
                    mergingBatch->getClipSideFlags(),
                    mergingBatch->getClipRect()
            };
            if (data.clipSideFlags) {
                // if right or bottom sides aren't used to clip, init them to viewport bounds
                // in the clip rect, so it can be used to scissor
                if (!(data.clipSideFlags & OpClipSideFlags::Right)) data.clip.right = width;
                if (!(data.clipSideFlags & OpClipSideFlags::Bottom)) data.clip.bottom = height;
            }
            mergedReceivers[opId](arg, data);
        } else {
            for (const BakedOpState* op : batch->getOps()) {
@@ -850,14 +846,16 @@ void OpReorderer::deferSimpleRectsOp(const SimpleRectsOp& op) {
    currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Vertices);
}

static batchid_t textBatchId(const SkPaint& paint) {
    // TODO: better handling of shader (since we won't care about color then)
    return paint.getColor() == SK_ColorBLACK ? OpBatchType::Text : OpBatchType::ColorText;
}

void OpReorderer::deferTextOp(const TextOp& op) {
    BakedOpState* bakedState = tryBakeOpState(op);
    if (!bakedState) return; // quick rejected

    // TODO: better handling of shader (since we won't care about color then)
    batchid_t batchId = op.paint->getColor() == SK_ColorBLACK
            ? OpBatchType::Text : OpBatchType::ColorText;

    batchid_t batchId = textBatchId(*(op.paint));
    if (bakedState->computedState.transform.isPureTranslate()
            && PaintUtils::getXfermodeDirect(op.paint) == SkXfermode::kSrcOver_Mode) {
        mergeid_t mergeId = reinterpret_cast<mergeid_t>(op.paint->getColor());
@@ -867,6 +865,12 @@ void OpReorderer::deferTextOp(const TextOp& op) {
    }
}

void OpReorderer::deferTextOnPathOp(const TextOnPathOp& op) {
    BakedOpState* bakedState = tryBakeOpState(op);
    if (!bakedState) return; // quick rejected
    currentLayer().deferUnmergeableOp(mAllocator, bakedState, textBatchId(*(op.paint)));
}

void OpReorderer::saveForLayer(uint32_t layerWidth, uint32_t layerHeight,
        float contentTranslateX, float contentTranslateY,
        const Rect& repaintRect,
+18 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ struct Vertex;
        U_OP_FN(ShadowOp) \
        U_OP_FN(SimpleRectsOp) \
        M_OP_FN(TextOp) \
        U_OP_FN(TextOnPathOp) \
        U_OP_FN(BeginLayerOp) \
        U_OP_FN(EndLayerOp) \
        U_OP_FN(LayerOp)
@@ -327,6 +328,23 @@ struct TextOp : RecordedOp {
    const float y;
};

struct TextOnPathOp : RecordedOp {
    TextOnPathOp(BASE_PARAMS, const glyph_t* glyphs, int glyphCount,
            const SkPath* path, float hOffset, float vOffset)
            : SUPER(TextOnPathOp)
            , glyphs(glyphs)
            , glyphCount(glyphCount)
            , path(path)
            , hOffset(hOffset)
            , vOffset(vOffset) {}
    const glyph_t* glyphs;
    const int glyphCount;

    const SkPath* path;
    const float hOffset;
    const float vOffset;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Layers
////////////////////////////////////////////////////////////////////////////////////////////////////
+8 −2
Original line number Diff line number Diff line
@@ -503,9 +503,15 @@ void RecordingCanvas::drawText(const uint16_t* glyphs, const float* positions, i
    drawTextDecorations(x, y, totalAdvance, paint);
}

void RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
void RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int glyphCount, const SkPath& path,
            float hOffset, float vOffset, const SkPaint& paint) {
    LOG_ALWAYS_FATAL("TODO!");
    if (!glyphs || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
    glyphs = refBuffer<glyph_t>(glyphs, glyphCount);
    addOp(new (alloc()) TextOnPathOp(
            mState.getRenderTargetClipBounds(), // TODO: explicitly define bounds
            *(mState.currentSnapshot()->transform),
            mState.getRenderTargetClipBounds(),
            refPaint(&paint), glyphs, glyphCount, refPath(&path), hOffset, vOffset));
}

void RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
Loading