move insertSubRunOpsIntoTarget into GrRenderTargetContext

Change-Id: I1ba96ac0951aa89a076b9ad1383b5ae172e4266f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/301382
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Herb Derby <herb@google.com>
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 1fbdcdc..3993733 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -555,8 +555,107 @@
     }
 
     for (GrTextBlob::SubRun* subRun : blob->subRunList()) {
-        subRun->insertSubRunOpsIntoTarget(
-                fTextTarget.get(), fSurfaceProps, blobPaint, clip, matrixProvider, drawOrigin);
+        if (subRun->drawAsPaths()) {
+            SkASSERT(!subRun->paths().empty());
+            SkPaint runPaint{blobPaint};
+            runPaint.setAntiAlias(subRun->isAntiAliased());
+            // If there are shaders, blurs or styles, the path must be scaled into source
+            // space independently of the CTM. This allows the CTM to be correct for the
+            // different effects.
+            GrStyle style(runPaint);
+
+            bool needsExactCTM = runPaint.getShader()
+                                 || style.applies()
+                                 || runPaint.getMaskFilter();
+
+            // Calculate the matrix that maps the path glyphs from their size in the strike to
+            // the graphics source space.
+            SkScalar scale = subRun->strikeSpec().strikeToSourceRatio();
+            SkMatrix strikeToSource = SkMatrix::Scale(scale, scale);
+            strikeToSource.postTranslate(drawOrigin.x(), drawOrigin.y());
+            if (!needsExactCTM) {
+                for (const auto& pathPos : subRun->paths()) {
+                    const SkPath& path = pathPos.fPath;
+                    const SkPoint pos = pathPos.fOrigin;  // Transform the glyph to source space.
+                    SkMatrix pathMatrix = strikeToSource;
+                    pathMatrix.postTranslate(pos.x(), pos.y());
+                    SkPreConcatMatrixProvider strikeToDevice(matrixProvider, pathMatrix);
+
+                    GrStyledShape shape(path, blobPaint);
+                    GrBlurUtils::drawShapeWithMaskFilter(
+                            this->fContext, this, clip, runPaint, strikeToDevice, shape);
+                }
+            } else {
+                // Transform the path to device because the deviceMatrix must be unchanged to
+                // draw effect, filter or shader paths.
+                for (const auto& pathPos : subRun->paths()) {
+                    const SkPath& path = pathPos.fPath;
+                    const SkPoint pos = pathPos.fOrigin;
+                    // Transform the glyph to source space.
+                    SkMatrix pathMatrix = strikeToSource;
+                    pathMatrix.postTranslate(pos.x(), pos.y());
+
+                    SkPath deviceOutline;
+                    path.transform(pathMatrix, &deviceOutline);
+                    deviceOutline.setIsVolatile(true);
+                    GrStyledShape shape(deviceOutline, blobPaint);
+                    GrBlurUtils::drawShapeWithMaskFilter(
+                            this->fContext, this, clip, runPaint, matrixProvider, shape);
+                }
+            }
+        } else {
+            // Handle the mask and distance field cases.
+            SkASSERT(subRun->glyphCount() != 0);
+
+            // We can clip geometrically using clipRect and ignore clip if we're not using SDFs or
+            // transformed glyphs, and we have an axis-aligned rectangular non-AA clip.
+            std::unique_ptr<GrAtlasTextOp> op;
+            const GrClip* subRunClip = clip;
+            if (!subRun->drawAsDistanceFields()) {
+                SkIRect clipRect = SkIRect::MakeEmpty();
+                if (!subRun->needsTransform()) {
+                    // We only need to do clipping work if the SubRun isn't contained by the clip
+                    SkRect subRunBounds = subRun->deviceRect(
+                            matrixProvider.localToDevice(), drawOrigin);
+                    SkRect renderTargetBounds = SkRect::MakeWH(this->width(), this->height());
+                    if (subRunClip == nullptr && !renderTargetBounds.intersects(subRunBounds)) {
+                        // If the SubRun is completely outside, don't add an op for it.
+                        continue;
+                    } else if (subRunClip != nullptr) {
+                        GrClip::PreClipResult result = subRunClip->preApply(subRunBounds);
+                        if (result.fEffect == GrClip::Effect::kClipped) {
+                            if (result.fIsRRect && result.fRRect.isRect() &&
+                                result.fAA == GrAA::kNo) {
+                                // Clip geometrically during onPrepare using clipRect.
+                                result.fRRect.getBounds().round(&clipRect);
+                                subRunClip = nullptr;
+                            }
+                        } else if (result.fEffect == GrClip::Effect::kClippedOut) {
+                            continue;
+                        }
+                    }
+                }
+
+                if (!clipRect.isEmpty()) { SkASSERT(subRunClip == nullptr); }
+
+                op = GrAtlasTextOp::MakeBitmap(this,
+                                               blobPaint,
+                                               subRun,
+                                               matrixProvider,
+                                               drawOrigin,
+                                               clipRect);
+            } else {
+                op = GrAtlasTextOp::MakeDistanceField(this,
+                                                      blobPaint,
+                                                      subRun,
+                                                      matrixProvider,
+                                                      drawOrigin);
+            }
+
+            if (op != nullptr) {
+                this->addDrawOp(subRunClip, std::move(op));
+            }
+        }
     }
 }