• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/core/SkColorFilter.h"
9 #include "include/core/SkRSXform.h"
10 #include "src/core/SkBlendModePriv.h"
11 #include "src/core/SkColorSpacePriv.h"
12 #include "src/core/SkColorSpaceXformSteps.h"
13 #include "src/core/SkCoreBlitters.h"
14 #include "src/core/SkDraw.h"
15 #include "src/core/SkRasterPipeline.h"
16 #include "src/core/SkScan.h"
17 #include "src/shaders/SkShaderBase.h"
18 
19 #include "include/core/SkMatrix.h"
20 #include "src/core/SkScan.h"
21 
fill_rect(const SkMatrix & ctm,const SkRasterClip & rc,const SkRect & r,SkBlitter * blitter)22 static void fill_rect(const SkMatrix& ctm, const SkRasterClip& rc,
23                       const SkRect& r, SkBlitter* blitter) {
24     if (ctm.rectStaysRect()) {
25         SkRect dr;
26         ctm.mapRect(&dr, r);
27         SkScan::FillRect(dr, rc, blitter);
28     } else {
29         SkPath path;
30         path.addRect(r);
31         path.transform(ctm);
32         SkScan::FillPath(path, rc, blitter);
33     }
34 }
35 
load_color(SkRasterPipeline_UniformColorCtx * ctx,const float rgba[])36 static void load_color(SkRasterPipeline_UniformColorCtx* ctx, const float rgba[]) {
37     // only need one of these. can I query the pipeline to know if its lowp or highp?
38     ctx->rgba[0] = SkScalarRoundToInt(rgba[0]*255); ctx->r = rgba[0];
39     ctx->rgba[1] = SkScalarRoundToInt(rgba[1]*255); ctx->g = rgba[1];
40     ctx->rgba[2] = SkScalarRoundToInt(rgba[2]*255); ctx->b = rgba[2];
41     ctx->rgba[3] = SkScalarRoundToInt(rgba[3]*255); ctx->a = rgba[3];
42 }
43 
drawAtlas(const SkImage * atlas,const SkRSXform xform[],const SkRect textures[],const SkColor colors[],int count,SkBlendMode bmode,const SkPaint & paint)44 void SkDraw::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect textures[],
45                        const SkColor colors[], int count, SkBlendMode bmode, const SkPaint& paint) {
46     sk_sp<SkShader> atlasShader = atlas->makeShader();
47     if (!atlasShader) {
48         return;
49     }
50 
51     SkPaint p(paint);
52     p.setAntiAlias(false);  // we never respect this for drawAtlas(or drawVertices)
53     p.setStyle(SkPaint::kFill_Style);
54     p.setShader(nullptr);
55     p.setMaskFilter(nullptr);
56 
57     SkSTArenaAlloc<256> alloc;
58     SkRasterPipeline pipeline(&alloc);
59     SkStageRec rec = {
60         &pipeline, &alloc, fDst.colorType(), fDst.colorSpace(), p, nullptr, *fMatrix
61     };
62 
63     SkStageUpdater* updator = as_SB(atlasShader.get())->appendUpdatableStages(rec);
64     if (!updator) {
65         SkDraw draw(*this);
66 
67         p.setShader(atlasShader);
68         for (int i = 0; i < count; ++i) {
69             if (colors) {
70                 p.setShader(SkShaders::Blend(bmode, SkShaders::Color(colors[i]), atlasShader));
71             }
72             SkMatrix mx;
73             mx.setRSXform(xform[i]);
74             mx.preTranslate(-textures[i].fLeft, -textures[i].fTop);
75             mx.postConcat(*fMatrix);
76             draw.fMatrix = &mx;
77             draw.drawRect(textures[i], p);
78         }
79         return;
80     }
81 
82     SkRasterPipeline_UniformColorCtx* uniformCtx = nullptr;
83     SkColorSpaceXformSteps steps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
84                                  rec.fDstCS,          kUnpremul_SkAlphaType);
85 
86     if (colors) {
87         // we will late-bind the values in ctx, once for each color in the loop
88         uniformCtx = alloc.make<SkRasterPipeline_UniformColorCtx>();
89         rec.fPipeline->append(SkRasterPipeline::uniform_color_dst, uniformCtx);
90         SkBlendMode_AppendStages(bmode, rec.fPipeline);
91     }
92 
93     bool isOpaque = !colors && atlasShader->isOpaque();
94     if (p.getAlphaf() != 1) {
95         rec.fPipeline->append(SkRasterPipeline::scale_1_float, alloc.make<float>(p.getAlphaf()));
96         isOpaque = false;
97     }
98 
99     auto blitter = SkCreateRasterPipelineBlitter(fDst, p, pipeline, isOpaque, &alloc);
100 
101     for (int i = 0; i < count; ++i) {
102         if (colors) {
103             SkColor4f c4 = SkColor4f::FromColor(colors[i]);
104             steps.apply(c4.vec());
105             load_color(uniformCtx, c4.premul().vec());
106         }
107 
108         SkMatrix mx;
109         mx.setRSXform(xform[i]);
110         mx.preTranslate(-textures[i].fLeft, -textures[i].fTop);
111         mx.postConcat(*fMatrix);
112 
113         updator->update(mx, nullptr);
114         fill_rect(mx, *fRC, textures[i], blitter);
115     }
116 }
117