Flutter Engine
The Flutter Engine
Typedefs | Functions | Variables
SkPDFGradientShader.cpp File Reference
#include "src/pdf/SkPDFGradientShader.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPathTypes.h"
#include "include/core/SkSpan.h"
#include "include/core/SkStream.h"
#include "include/core/SkTileMode.h"
#include "include/private/base/SkTemplates.h"
#include "include/private/base/SkTo.h"
#include "src/core/SkChecksum.h"
#include "src/core/SkTHash.h"
#include "src/pdf/SkPDFDocumentPriv.h"
#include "src/pdf/SkPDFFormXObject.h"
#include "src/pdf/SkPDFGraphicState.h"
#include "src/pdf/SkPDFResourceDict.h"
#include "src/pdf/SkPDFTypes.h"
#include "src/pdf/SkPDFUtils.h"
#include <cmath>
#include <cstddef>
#include <utility>
#include <vector>

Go to the source code of this file.

Typedefs

typedef uint8_t ColorTuple[kColorComponents]
 

Functions

static uint32_t hash (const SkShaderBase::GradientInfo &v)
 
static uint32_t hash (const SkPDFGradientShader::Key &k)
 
static void unit_to_points_matrix (const SkPoint pts[2], SkMatrix *matrix)
 
static void interpolate_color_code (SkScalar range, SkColor beginColor, SkColor endColor, SkDynamicMemoryWStream *result)
 
static void write_gradient_ranges (const SkShaderBase::GradientInfo &info, SkSpan< size_t > rangeEnds, bool top, bool first, SkDynamicMemoryWStream *result)
 
static void gradient_function_code (const SkShaderBase::GradientInfo &info, SkDynamicMemoryWStream *result)
 
static std::unique_ptr< SkPDFDictcreateInterpolationFunction (const ColorTuple &color1, const ColorTuple &color2)
 
static std::unique_ptr< SkPDFDictgradientStitchCode (const SkShaderBase::GradientInfo &info)
 
static void tileModeCode (SkTileMode mode, SkDynamicMemoryWStream *result)
 
static void apply_perspective_to_coordinates (const SkMatrix &inversePerspectiveMatrix, SkDynamicMemoryWStream *code)
 
static void linearCode (const SkShaderBase::GradientInfo &info, const SkMatrix &perspectiveRemover, SkDynamicMemoryWStream *function)
 
static void radialCode (const SkShaderBase::GradientInfo &info, const SkMatrix &perspectiveRemover, SkDynamicMemoryWStream *function)
 
static void twoPointConicalCode (const SkShaderBase::GradientInfo &info, const SkMatrix &perspectiveRemover, SkDynamicMemoryWStream *function)
 
static void sweepCode (const SkShaderBase::GradientInfo &info, const SkMatrix &perspectiveRemover, SkDynamicMemoryWStream *function)
 
static void FixUpRadius (const SkPoint &p1, SkScalar &r1, const SkPoint &p2, SkScalar &r2)
 
static bool split_perspective (const SkMatrix in, SkMatrix *affine, SkMatrix *perspectiveInverse)
 
static SkPDFIndirectReference make_ps_function (std::unique_ptr< SkStreamAsset > psCode, std::unique_ptr< SkPDFArray > domain, std::unique_ptr< SkPDFObject > range, SkPDFDocument *doc)
 
static SkPDFIndirectReference make_function_shader (SkPDFDocument *doc, const SkPDFGradientShader::Key &state)
 
static SkPDFIndirectReference find_pdf_shader (SkPDFDocument *doc, SkPDFGradientShader::Key key, bool keyHasAlpha)
 
static std::unique_ptr< SkPDFDictget_gradient_resource_dict (SkPDFIndirectReference functionShader, SkPDFIndirectReference gState)
 
static std::unique_ptr< SkStreamAssetcreate_pattern_fill_content (int gsIndex, int patternIndex, SkRect &bounds)
 
static bool gradient_has_alpha (const SkPDFGradientShader::Key &key)
 
static SkPDFGradientShader::Key clone_key (const SkPDFGradientShader::Key &k)
 
static SkPDFIndirectReference create_smask_graphic_state (SkPDFDocument *doc, const SkPDFGradientShader::Key &state)
 
static SkPDFIndirectReference make_alpha_function_shader (SkPDFDocument *doc, const SkPDFGradientShader::Key &state)
 
static SkPDFGradientShader::Key make_key (const SkShader *shader, const SkMatrix &canvasTransform, const SkIRect &bbox)
 

Variables

static const int kColorComponents = 3
 

Typedef Documentation

◆ ColorTuple

typedef uint8_t ColorTuple[kColorComponents]

Definition at line 69 of file SkPDFGradientShader.cpp.

Function Documentation

◆ apply_perspective_to_coordinates()

static void apply_perspective_to_coordinates ( const SkMatrix inversePerspectiveMatrix,
SkDynamicMemoryWStream code 
)
static

Returns PS function code that applies inverse perspective to a x, y point. The function assumes that the stack has at least two elements, and that the top 2 elements are numeric values. After executing this code on a PS stack, the last 2 elements are updated while the rest of the stack is preserved intact. inversePerspectiveMatrix is the inverse perspective matrix.

Definition at line 432 of file SkPDFGradientShader.cpp.

433 {
434 if (!inversePerspectiveMatrix.hasPerspective()) {
435 return;
436 }
437
438 // Perspective matrix should be:
439 // 1 0 0
440 // 0 1 0
441 // p0 p1 p2
442
443 const SkScalar p0 = inversePerspectiveMatrix[SkMatrix::kMPersp0];
444 const SkScalar p1 = inversePerspectiveMatrix[SkMatrix::kMPersp1];
445 const SkScalar p2 = inversePerspectiveMatrix[SkMatrix::kMPersp2];
446
447 // y = y / (p2 + p0 x + p1 y)
448 // x = x / (p2 + p0 x + p1 y)
449
450 // Input on stack: x y
451 code->writeText(" dup "); // x y y
452 SkPDFUtils::AppendScalar(p1, code); // x y y p1
453 code->writeText(" mul " // x y y*p1
454 " 2 index "); // x y y*p1 x
455 SkPDFUtils::AppendScalar(p0, code); // x y y p1 x p0
456 code->writeText(" mul "); // x y y*p1 x*p0
457 SkPDFUtils::AppendScalar(p2, code); // x y y p1 x*p0 p2
458 code->writeText(" add " // x y y*p1 x*p0+p2
459 "add " // x y y*p1+x*p0+p2
460 "3 1 roll " // y*p1+x*p0+p2 x y
461 "2 index " // z x y y*p1+x*p0+p2
462 "div " // y*p1+x*p0+p2 x y/(y*p1+x*p0+p2)
463 "3 1 roll " // y/(y*p1+x*p0+p2) y*p1+x*p0+p2 x
464 "exch " // y/(y*p1+x*p0+p2) x y*p1+x*p0+p2
465 "div " // y/(y*p1+x*p0+p2) x/(y*p1+x*p0+p2)
466 "exch\n"); // x/(y*p1+x*p0+p2) y/(y*p1+x*p0+p2)
467}
static constexpr int kMPersp1
input y perspective factor
Definition: SkMatrix.h:360
static constexpr int kMPersp0
input x perspective factor
Definition: SkMatrix.h:359
static constexpr int kMPersp2
perspective bias
Definition: SkMatrix.h:361
bool hasPerspective() const
Definition: SkMatrix.h:312
float SkScalar
Definition: extension.cpp:12
void AppendScalar(SkScalar value, SkWStream *stream)
Definition: SkPDFUtils.h:98

◆ clone_key()

static SkPDFGradientShader::Key clone_key ( const SkPDFGradientShader::Key k)
static

Definition at line 914 of file SkPDFGradientShader.cpp.

914 {
916 k.fType,
917 k.fInfo, // change pointers later.
918 std::unique_ptr<SkColor[]>(new SkColor[k.fInfo.fColorCount]),
919 std::unique_ptr<SkScalar[]>(new SkScalar[k.fInfo.fColorCount]),
922 k.fBBox, 0};
923 clone.fInfo.fColors = clone.fColors.get();
924 clone.fInfo.fColorOffsets = clone.fStops.get();
925 for (int i = 0; i < clone.fInfo.fColorCount; i++) {
927 clone.fInfo.fColors[i] = k.fInfo.fColors[i];
928 }
929 return clone;
930}
uint32_t SkColor
Definition: SkColor.h:37
SkShaderBase::GradientType fType
std::unique_ptr< SkScalar[]> fStops
std::unique_ptr< SkColor[]> fColors
SkShaderBase::GradientInfo fInfo
SkColor * fColors
The colors in the gradient.
Definition: SkShaderBase.h:247
int fColorCount
In-out parameter, specifies passed size.
Definition: SkShaderBase.h:243
SkScalar * fColorOffsets
The unit offset for color transitions.
Definition: SkShaderBase.h:248

◆ create_pattern_fill_content()

static std::unique_ptr< SkStreamAsset > create_pattern_fill_content ( int  gsIndex,
int  patternIndex,
SkRect bounds 
)
static

Definition at line 890 of file SkPDFGradientShader.cpp.

892 {
894 if (gsIndex >= 0) {
896 }
897 SkPDFUtils::ApplyPattern(patternIndex, &content);
900 return content.detachAsStream();
901}
@ kFill_Style
set to fill geometry
Definition: SkPaint.h:193
union flutter::testing::@2836::KeyboardChange::@76 content
void ApplyGraphicState(int objectIndex, SkWStream *content)
Definition: SkPDFUtils.cpp:254
void AppendRectangle(const SkRect &rect, SkWStream *content)
Definition: SkPDFUtils.cpp:118
void PaintPath(SkPaint::Style style, SkPathFillType fill, SkWStream *content)
Definition: SkPDFUtils.cpp:231
void ApplyPattern(int objectIndex, SkWStream *content)
Definition: SkPDFUtils.cpp:259
Optional< SkRect > bounds
Definition: SkRecords.h:189

◆ create_smask_graphic_state()

static SkPDFIndirectReference create_smask_graphic_state ( SkPDFDocument doc,
const SkPDFGradientShader::Key state 
)
static

Definition at line 932 of file SkPDFGradientShader.cpp.

933 {
935 SkPDFGradientShader::Key luminosityState = clone_key(state);
936 for (int i = 0; i < luminosityState.fInfo.fColorCount; i++) {
937 SkAlpha alpha = SkColorGetA(luminosityState.fInfo.fColors[i]);
938 luminosityState.fInfo.fColors[i] = SkColorSetARGB(255, alpha, alpha, alpha);
939 }
940 luminosityState.fHash = hash(luminosityState);
941
942 SkASSERT(!gradient_has_alpha(luminosityState));
943 SkPDFIndirectReference luminosityShader = find_pdf_shader(doc, std::move(luminosityState), false);
944 std::unique_ptr<SkPDFDict> resources = get_gradient_resource_dict(luminosityShader,
946 SkRect bbox = SkRect::Make(state.fBBox);
947 SkPDFIndirectReference alphaMask =
949 create_pattern_fill_content(-1, luminosityShader.fValue, bbox),
951 std::move(resources),
952 SkMatrix::I(),
953 "DeviceRGB");
955 alphaMask, false, SkPDFGraphicState::kLuminosity_SMaskMode, doc);
956}
#define SkASSERT(cond)
Definition: SkAssert.h:116
uint8_t SkAlpha
Definition: SkColor.h:26
static constexpr SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition: SkColor.h:49
#define SkColorGetA(color)
Definition: SkColor.h:61
SkPDFIndirectReference SkPDFMakeFormXObject(SkPDFDocument *doc, std::unique_ptr< SkStreamAsset > content, std::unique_ptr< SkPDFArray > mediaBox, std::unique_ptr< SkPDFDict > resourceDict, const SkMatrix &inverseTransform, const char *colorSpace)
static std::unique_ptr< SkPDFDict > get_gradient_resource_dict(SkPDFIndirectReference functionShader, SkPDFIndirectReference gState)
static SkPDFGradientShader::Key clone_key(const SkPDFGradientShader::Key &k)
static SkPDFIndirectReference find_pdf_shader(SkPDFDocument *doc, SkPDFGradientShader::Key key, bool keyHasAlpha)
static bool gradient_has_alpha(const SkPDFGradientShader::Key &key)
static uint32_t hash(const SkShaderBase::GradientInfo &v)
static std::unique_ptr< SkStreamAsset > create_pattern_fill_content(int gsIndex, int patternIndex, SkRect &bounds)
static const SkMatrix & I()
Definition: SkMatrix.cpp:1544
AtkStateType state
SkPDFIndirectReference GetSMaskGraphicState(SkPDFIndirectReference sMask, bool invert, SkPDFSMaskMode sMaskMode, SkPDFDocument *doc)
std::unique_ptr< SkPDFArray > RectToArray(const SkRect &rect)
Definition: SkPDFUtils.cpp:63
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669

◆ createInterpolationFunction()

static std::unique_ptr< SkPDFDict > createInterpolationFunction ( const ColorTuple color1,
const ColorTuple color2 
)
static

Definition at line 298 of file SkPDFGradientShader.cpp.

299 {
300 auto retval = SkPDFMakeDict();
301
302 auto c0 = SkPDFMakeArray();
303 c0->appendColorComponent(color1[0]);
304 c0->appendColorComponent(color1[1]);
305 c0->appendColorComponent(color1[2]);
306 retval->insertObject("C0", std::move(c0));
307
308 auto c1 = SkPDFMakeArray();
309 c1->appendColorComponent(color2[0]);
310 c1->appendColorComponent(color2[1]);
311 c1->appendColorComponent(color2[2]);
312 retval->insertObject("C1", std::move(c1));
313
314 retval->insertObject("Domain", SkPDFMakeArray(0, 1));
315
316 retval->insertInt("FunctionType", 2);
317 retval->insertScalar("N", 1.0f);
318
319 return retval;
320}
static std::unique_ptr< SkPDFDict > SkPDFMakeDict(const char *type=nullptr)
Definition: SkPDFTypes.h:185
static std::unique_ptr< SkPDFArray > SkPDFMakeArray(Args... args)
Definition: SkPDFTypes.h:125

◆ find_pdf_shader()

static SkPDFIndirectReference find_pdf_shader ( SkPDFDocument doc,
SkPDFGradientShader::Key  key,
bool  keyHasAlpha 
)
static

Definition at line 1010 of file SkPDFGradientShader.cpp.

1012 {
1013 SkASSERT(gradient_has_alpha(key) == keyHasAlpha);
1014 auto& gradientPatternMap = doc->fGradientPatternMap;
1015 if (SkPDFIndirectReference* ptr = gradientPatternMap.find(key)) {
1016 return *ptr;
1017 }
1018 SkPDFIndirectReference pdfShader;
1019 if (keyHasAlpha) {
1020 pdfShader = make_alpha_function_shader(doc, key);
1021 } else {
1022 pdfShader = make_function_shader(doc, key);
1023 }
1024 gradientPatternMap.set(std::move(key), pdfShader);
1025 return pdfShader;
1026}
static SkPDFIndirectReference make_function_shader(SkPDFDocument *doc, const SkPDFGradientShader::Key &state)
static SkPDFIndirectReference make_alpha_function_shader(SkPDFDocument *doc, const SkPDFGradientShader::Key &state)
skia_private::THashMap< SkPDFGradientShader::Key, SkPDFIndirectReference, SkPDFGradientShader::KeyHash > fGradientPatternMap

◆ FixUpRadius()

static void FixUpRadius ( const SkPoint p1,
SkScalar r1,
const SkPoint p2,
SkScalar r2 
)
static

Definition at line 632 of file SkPDFGradientShader.cpp.

632 {
633 // detect touching circles
635 SkScalar subtractRadii = fabs(r1 - r2);
636 if (fabs(distance - subtractRadii) < 0.002f) {
637 if (r1 > r2) {
638 r1 += 0.002f;
639 } else {
640 r2 += 0.002f;
641 }
642 }
643}
static float Distance(const SkPoint &a, const SkPoint &b)
Definition: SkPoint_impl.h:508

◆ get_gradient_resource_dict()

static std::unique_ptr< SkPDFDict > get_gradient_resource_dict ( SkPDFIndirectReference  functionShader,
SkPDFIndirectReference  gState 
)
static

Definition at line 871 of file SkPDFGradientShader.cpp.

872 {
873 std::vector<SkPDFIndirectReference> patternShaders;
874 if (functionShader != SkPDFIndirectReference()) {
875 patternShaders.push_back(functionShader);
876 }
877 std::vector<SkPDFIndirectReference> graphicStates;
878 if (gState != SkPDFIndirectReference()) {
879 graphicStates.push_back(gState);
880 }
881 return SkPDFMakeResourceDict(std::move(graphicStates),
882 std::move(patternShaders),
883 std::vector<SkPDFIndirectReference>(),
884 std::vector<SkPDFIndirectReference>());
885}
std::unique_ptr< SkPDFDict > SkPDFMakeResourceDict(const std::vector< SkPDFIndirectReference > &graphicStateResources, const std::vector< SkPDFIndirectReference > &shaderResources, const std::vector< SkPDFIndirectReference > &xObjectResources, const std::vector< SkPDFIndirectReference > &fontResources)

◆ gradient_function_code()

static void gradient_function_code ( const SkShaderBase::GradientInfo info,
SkDynamicMemoryWStream result 
)
static

Definition at line 246 of file SkPDFGradientShader.cpp.

247 {
248 // While looking for a hit the stack is [t].
249 // After finding a hit the stack is [r g b 0].
250 // The 0 is consumed just before returning.
251
252 // The initial range has no previous and contains a solid color.
253 // Any t <= 0 will be handled by this initial range, so later t == 0 indicates a hit was found.
254 result->writeText("dup 0 le {pop ");
256 result->writeText(" ");
258 result->writeText(" ");
260 result->writeText(" 0} if\n");
261
262 // Optimize out ranges which don't make any visual difference.
263 AutoSTMalloc<4, size_t> rangeEnds(info.fColorCount);
264 size_t rangeEndsCount = 0;
265 for (int i = 1; i < info.fColorCount; ++i) {
266 // Ignoring the alpha, is this range the same solid color as the next range?
267 // This optimizes gradients where sometimes only the color or only the alpha is changing.
268 auto eqIgnoringAlpha = [](SkColor a, SkColor b) {
269 return SkColorSetA(a, 0x00) == SkColorSetA(b, 0x00);
270 };
271 bool constantColorBothSides =
272 eqIgnoringAlpha(info.fColors[i-1], info.fColors[i]) &&// This range is a solid color.
273 i != info.fColorCount-1 && // This is not the last range.
274 eqIgnoringAlpha(info.fColors[i], info.fColors[i+1]); // Next range is same solid color.
275
276 // Does this range have zero size?
277 bool degenerateRange = info.fColorOffsets[i-1] == info.fColorOffsets[i];
278
279 if (!degenerateRange && !constantColorBothSides) {
280 rangeEnds[rangeEndsCount] = i;
281 ++rangeEndsCount;
282 }
283 }
284
285 // If a cap on depth is needed, loop here.
286 write_gradient_ranges(info, SkSpan(rangeEnds.get(), rangeEndsCount), true, true, result);
287
288 // Clamp the final color.
289 result->writeText("0 gt {");
290 SkPDFUtils::AppendColorComponent(SkColorGetR(info.fColors[info.fColorCount - 1]), result);
291 result->writeText(" ");
292 SkPDFUtils::AppendColorComponent(SkColorGetG(info.fColors[info.fColorCount - 1]), result);
293 result->writeText(" ");
294 SkPDFUtils::AppendColorComponent(SkColorGetB(info.fColors[info.fColorCount - 1]), result);
295 result->writeText("} if\n");
296}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
#define SkColorGetR(color)
Definition: SkColor.h:65
#define SkColorGetG(color)
Definition: SkColor.h:69
static constexpr SkColor SkColorSetA(SkColor c, U8CPU a)
Definition: SkColor.h:82
#define SkColorGetB(color)
Definition: SkColor.h:73
static void write_gradient_ranges(const SkShaderBase::GradientInfo &info, SkSpan< size_t > rangeEnds, bool top, bool first, SkDynamicMemoryWStream *result)
SkSpan(Container &&) -> SkSpan< std::remove_pointer_t< decltype(std::data(std::declval< Container >()))> >
static bool b
struct MyStruct a[10]
GAsyncResult * result
void AppendColorComponent(uint8_t value, SkWStream *wStream)
Definition: SkPDFUtils.h:87

◆ gradient_has_alpha()

static bool gradient_has_alpha ( const SkPDFGradientShader::Key key)
static

Definition at line 903 of file SkPDFGradientShader.cpp.

903 {
905 for (int i = 0; i < key.fInfo.fColorCount; i++) {
906 if ((SkAlpha)SkColorGetA(key.fInfo.fColors[i]) != SK_AlphaOPAQUE) {
907 return true;
908 }
909 }
910 return false;
911}
constexpr SkAlpha SK_AlphaOPAQUE
Definition: SkColor.h:94

◆ gradientStitchCode()

static std::unique_ptr< SkPDFDict > gradientStitchCode ( const SkShaderBase::GradientInfo info)
static

Definition at line 322 of file SkPDFGradientShader.cpp.

322 {
323 auto retval = SkPDFMakeDict();
324
325 // normalize color stops
326 int colorCount = info.fColorCount;
327 std::vector<SkColor> colors(info.fColors, info.fColors + colorCount);
328 std::vector<SkScalar> colorOffsets(info.fColorOffsets, info.fColorOffsets + colorCount);
329
330 int i = 1;
331 while (i < colorCount - 1) {
332 // ensure stops are in order
333 if (colorOffsets[i - 1] > colorOffsets[i]) {
334 colorOffsets[i] = colorOffsets[i - 1];
335 }
336
337 // remove points that are between 2 coincident points
338 if ((colorOffsets[i - 1] == colorOffsets[i]) && (colorOffsets[i] == colorOffsets[i + 1])) {
339 colorCount -= 1;
340 colors.erase(colors.begin() + i);
341 colorOffsets.erase(colorOffsets.begin() + i);
342 } else {
343 i++;
344 }
345 }
346 // find coincident points and slightly move them over
347 for (i = 1; i < colorCount - 1; i++) {
348 if (colorOffsets[i - 1] == colorOffsets[i]) {
349 colorOffsets[i] += 0.00001f;
350 }
351 }
352 // check if last 2 stops coincide
353 if (colorOffsets[i - 1] == colorOffsets[i]) {
354 colorOffsets[i - 1] -= 0.00001f;
355 }
356
357 AutoSTMalloc<4, ColorTuple> colorDataAlloc(colorCount);
358 ColorTuple *colorData = colorDataAlloc.get();
359 for (int idx = 0; idx < colorCount; idx++) {
360 colorData[idx][0] = SkColorGetR(colors[idx]);
361 colorData[idx][1] = SkColorGetG(colors[idx]);
362 colorData[idx][2] = SkColorGetB(colors[idx]);
363 }
364
365 // no need for a stitch function if there are only 2 stops.
366 if (colorCount == 2)
367 return createInterpolationFunction(colorData[0], colorData[1]);
368
369 auto encode = SkPDFMakeArray();
370 auto bounds = SkPDFMakeArray();
371 auto functions = SkPDFMakeArray();
372
373 retval->insertObject("Domain", SkPDFMakeArray(0, 1));
374 retval->insertInt("FunctionType", 3);
375
376 for (int idx = 1; idx < colorCount; idx++) {
377 if (idx > 1) {
378 bounds->appendScalar(colorOffsets[idx-1]);
379 }
380
381 encode->appendScalar(0);
382 encode->appendScalar(1.0f);
383
384 functions->appendObject(createInterpolationFunction(colorData[idx-1], colorData[idx]));
385 }
386
387 retval->insertObject("Encode", std::move(encode));
388 retval->insertObject("Bounds", std::move(bounds));
389 retval->insertObject("Functions", std::move(functions));
390
391 return retval;
392}
static void encode(uint8_t output[16], const uint32_t input[4])
Definition: SkMD5.cpp:240
static std::unique_ptr< SkPDFDict > createInterpolationFunction(const ColorTuple &color1, const ColorTuple &color2)
uint8_t ColorTuple[kColorComponents]
PODArray< SkColor > colors
Definition: SkRecords.h:276

◆ hash() [1/2]

static uint32_t hash ( const SkPDFGradientShader::Key k)
static

Definition at line 46 of file SkPDFGradientShader.cpp.

46 {
47 uint32_t buffer[] = {
48 (uint32_t)k.fType,
49 hash(k.fInfo),
53 };
54 return SkChecksum::Hash32(buffer, sizeof(buffer));
55}
uint32_t Hash32(const void *data, size_t bytes, uint32_t seed)
Definition: SkChecksum.cpp:113
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
Definition: SkRect.h:32

◆ hash() [2/2]

static uint32_t hash ( const SkShaderBase::GradientInfo v)
static

Definition at line 33 of file SkPDFGradientShader.cpp.

33 {
34 uint32_t buffer[] = {
35 (uint32_t)v.fColorCount,
38 SkChecksum::Hash32(v.fPoint, 2 * sizeof(SkPoint)),
39 SkChecksum::Hash32(v.fRadius, 2 * sizeof(SkScalar)),
40 (uint32_t)v.fTileMode,
42 };
43 return SkChecksum::Hash32(buffer, sizeof(buffer));
44}
uint32_t fGradientFlags
see SkGradientShader::Flags
Definition: SkShaderBase.h:252
SkPoint fPoint[2]
Type specific, see above.
Definition: SkShaderBase.h:249
SkScalar fRadius[2]
Type specific, see above.
Definition: SkShaderBase.h:250

◆ interpolate_color_code()

static void interpolate_color_code ( SkScalar  range,
SkColor  beginColor,
SkColor  endColor,
SkDynamicMemoryWStream result 
)
static

Definition at line 80 of file SkPDFGradientShader.cpp.

81 {
82 SkASSERT(range != SkIntToScalar(0));
83
84 /* Linearly interpolate from the previous color to the current.
85 Scale the colors from 0..255 to 0..1 and determine the multipliers for interpolation.
86 C{r,g,b}(t, section) = t - offset_(section-1) + t * Multiplier{r,g,b}.
87 */
88
89 ColorTuple curColor = { SkTo<uint8_t>(SkColorGetR(endColor)),
90 SkTo<uint8_t>(SkColorGetG(endColor)),
91 SkTo<uint8_t>(SkColorGetB(endColor)) };
92
93 ColorTuple prevColor = { SkTo<uint8_t>(SkColorGetR(beginColor)),
94 SkTo<uint8_t>(SkColorGetG(beginColor)),
95 SkTo<uint8_t>(SkColorGetB(beginColor)) };
96
97 // Figure out how to scale each color component.
98 SkScalar multiplier[kColorComponents];
99 for (int i = 0; i < kColorComponents; i++) {
100 static const SkScalar kColorScale = SkScalarInvert(255);
101 multiplier[i] = kColorScale * (curColor[i] - prevColor[i]) / range;
102 }
103
104 // Calculate when we no longer need to keep a copy of the input parameter t.
105 // If the last component to use t is i, then dupInput[0..i - 1] = true
106 // and dupInput[i .. components] = false.
107 bool dupInput[kColorComponents];
108 dupInput[kColorComponents - 1] = false;
109 for (int i = kColorComponents - 2; i >= 0; i--) {
110 dupInput[i] = dupInput[i + 1] || multiplier[i + 1] != 0;
111 }
112
113 if (!dupInput[0] && multiplier[0] == 0) {
114 result->writeText("pop ");
115 }
116
117 for (int i = 0; i < kColorComponents; i++) {
118 // If the next components needs t and this component will consume a
119 // copy, make another copy.
120 if (dupInput[i] && multiplier[i] != 0) {
121 result->writeText("dup ");
122 }
123
124 if (multiplier[i] == 0) {
126 result->writeText(" ");
127 } else {
128 if (multiplier[i] != 1) {
129 SkPDFUtils::AppendScalar(multiplier[i], result);
130 result->writeText(" mul ");
131 }
132 if (prevColor[i] != 0) {
134 result->writeText(" add ");
135 }
136 }
137
138 if (dupInput[i]) {
139 result->writeText("exch ");
140 }
141 }
142}
static const int kColorComponents
#define SkScalarInvert(x)
Definition: SkScalar.h:73
#define SkIntToScalar(x)
Definition: SkScalar.h:57

◆ linearCode()

static void linearCode ( const SkShaderBase::GradientInfo info,
const SkMatrix perspectiveRemover,
SkDynamicMemoryWStream function 
)
static

Definition at line 469 of file SkPDFGradientShader.cpp.

471 {
472 function->writeText("{");
473
474 apply_perspective_to_coordinates(perspectiveRemover, function);
475
476 function->writeText("pop\n"); // Just ditch the y value.
479 function->writeText("}");
480}
static void gradient_function_code(const SkShaderBase::GradientInfo &info, SkDynamicMemoryWStream *result)
static void tileModeCode(SkTileMode mode, SkDynamicMemoryWStream *result)
static void apply_perspective_to_coordinates(const SkMatrix &inversePerspectiveMatrix, SkDynamicMemoryWStream *code)
SkTileMode
Definition: SkTileMode.h:13
Dart_NativeFunction function
Definition: fuchsia.cc:51

◆ make_alpha_function_shader()

static SkPDFIndirectReference make_alpha_function_shader ( SkPDFDocument doc,
const SkPDFGradientShader::Key state 
)
static

Definition at line 958 of file SkPDFGradientShader.cpp.

959 {
962 for (int i = 0; i < opaqueState.fInfo.fColorCount; i++) {
963 opaqueState.fInfo.fColors[i] = SkColorSetA(opaqueState.fInfo.fColors[i], SK_AlphaOPAQUE);
964 }
965 opaqueState.fHash = hash(opaqueState);
966
967 SkASSERT(!gradient_has_alpha(opaqueState));
968 SkRect bbox = SkRect::Make(state.fBBox);
969 SkPDFIndirectReference colorShader = find_pdf_shader(doc, std::move(opaqueState), false);
970 if (!colorShader) {
971 return SkPDFIndirectReference();
972 }
973 // Create resource dict with alpha graphics state as G0 and
974 // pattern shader as P0, then write content stream.
976
977 std::unique_ptr<SkPDFDict> resourceDict = get_gradient_resource_dict(colorShader, alphaGsRef);
978
979 std::unique_ptr<SkStreamAsset> colorStream =
980 create_pattern_fill_content(alphaGsRef.fValue, colorShader.fValue, bbox);
981 std::unique_ptr<SkPDFDict> alphaFunctionShader = SkPDFMakeDict();
982 SkPDFUtils::PopulateTilingPatternDict(alphaFunctionShader.get(), bbox,
983 std::move(resourceDict), SkMatrix::I());
984 return SkPDFStreamOut(std::move(alphaFunctionShader), std::move(colorStream), doc);
985}
static SkPDFIndirectReference create_smask_graphic_state(SkPDFDocument *doc, const SkPDFGradientShader::Key &state)
SkPDFIndirectReference SkPDFStreamOut(std::unique_ptr< SkPDFDict > dict, std::unique_ptr< SkStreamAsset > content, SkPDFDocument *doc, SkPDFSteamCompressionEnabled compress)
Definition: SkPDFTypes.cpp:591
void PopulateTilingPatternDict(SkPDFDict *pattern, SkRect &bbox, std::unique_ptr< SkPDFDict > resources, const SkMatrix &matrix)
Definition: SkPDFUtils.cpp:327

◆ make_function_shader()

static SkPDFIndirectReference make_function_shader ( SkPDFDocument doc,
const SkPDFGradientShader::Key state 
)
static

Definition at line 694 of file SkPDFGradientShader.cpp.

695 {
696 SkPoint transformPoints[2];
698 SkMatrix finalMatrix = state.fCanvasTransform;
699 finalMatrix.preConcat(state.fShaderTransform);
700
701 bool doStitchFunctions = (state.fType == SkShaderBase::GradientType::kLinear ||
702 state.fType == SkShaderBase::GradientType::kRadial ||
703 state.fType == SkShaderBase::GradientType::kConical) &&
704 (info.fTileMode == SkTileMode::kClamp ||
705 info.fTileMode == SkTileMode::kDecal) &&
706 !finalMatrix.hasPerspective();
707
708 enum class ShadingType : int32_t {
709 Function = 1,
710 Axial = 2,
711 Radial = 3,
712 FreeFormGouraudTriangleMesh = 4,
713 LatticeFormGouraudTriangleMesh = 5,
714 CoonsPatchMesh = 6,
715 TensorProductPatchMesh = 7,
716 } shadingType;
717
718 auto pdfShader = SkPDFMakeDict();
719 if (doStitchFunctions) {
720 pdfShader->insertObject("Function", gradientStitchCode(info));
721
722 if (info.fTileMode == SkTileMode::kClamp) {
723 auto extend = SkPDFMakeArray();
724 extend->reserve(2);
725 extend->appendBool(true);
726 extend->appendBool(true);
727 pdfShader->insertObject("Extend", std::move(extend));
728 }
729
730 std::unique_ptr<SkPDFArray> coords;
731 switch (state.fType) {
733 shadingType = ShadingType::Axial;
734 const SkPoint& pt1 = info.fPoint[0];
735 const SkPoint& pt2 = info.fPoint[1];
736 coords = SkPDFMakeArray(pt1.x(), pt1.y(),
737 pt2.x(), pt2.y());
738 } break;
739 case SkShaderBase::GradientType::kRadial: {
740 shadingType = ShadingType::Radial;
741 const SkPoint& pt1 = info.fPoint[0];
742 coords = SkPDFMakeArray(pt1.x(), pt1.y(), 0,
743 pt1.x(), pt1.y(), info.fRadius[0]);
744 } break;
745 case SkShaderBase::GradientType::kConical: {
746 shadingType = ShadingType::Radial;
747 SkScalar r1 = info.fRadius[0];
748 SkScalar r2 = info.fRadius[1];
749 SkPoint pt1 = info.fPoint[0];
750 SkPoint pt2 = info.fPoint[1];
751 FixUpRadius(pt1, r1, pt2, r2);
752
753 coords = SkPDFMakeArray(pt1.x(), pt1.y(), r1,
754 pt2.x(), pt2.y(), r2);
755 break;
756 }
757 case SkShaderBase::GradientType::kSweep:
759 default:
760 SkASSERT(false);
761 return SkPDFIndirectReference();
762 }
763 pdfShader->insertObject("Coords", std::move(coords));
764 } else {
765 shadingType = ShadingType::Function;
766
767 // Transform the coordinate space for the type of gradient.
768 transformPoints[0] = info.fPoint[0];
769 transformPoints[1] = info.fPoint[1];
770 switch (state.fType) {
772 break;
773 case SkShaderBase::GradientType::kRadial:
774 transformPoints[1] = transformPoints[0];
775 transformPoints[1].fX += info.fRadius[0];
776 break;
777 case SkShaderBase::GradientType::kConical: {
778 transformPoints[1] = transformPoints[0];
779 transformPoints[1].fX += SK_Scalar1;
780 break;
781 }
782 case SkShaderBase::GradientType::kSweep:
783 transformPoints[1] = transformPoints[0];
784 transformPoints[1].fX += SK_Scalar1;
785 break;
787 default:
788 return SkPDFIndirectReference();
789 }
790
791 // Move any scaling (assuming a unit gradient) or translation
792 // (and rotation for linear gradient), of the final gradient from
793 // info.fPoints to the matrix (updating bbox appropriately). Now
794 // the gradient can be drawn on on the unit segment.
795 SkMatrix mapperMatrix;
796 unit_to_points_matrix(transformPoints, &mapperMatrix);
797
798 finalMatrix.preConcat(mapperMatrix);
799
800 // Preserves as much as possible in the final matrix, and only removes
801 // the perspective. The inverse of the perspective is stored in
802 // perspectiveInverseOnly matrix and has 3 useful numbers
803 // (p0, p1, p2), while everything else is either 0 or 1.
804 // In this way the shader will handle it eficiently, with minimal code.
805 SkMatrix perspectiveInverseOnly = SkMatrix::I();
806 if (finalMatrix.hasPerspective()) {
807 if (!split_perspective(finalMatrix,
808 &finalMatrix, &perspectiveInverseOnly)) {
809 return SkPDFIndirectReference();
810 }
811 }
812
813 SkRect bbox;
814 bbox.set(state.fBBox);
815 if (!SkPDFUtils::InverseTransformBBox(finalMatrix, &bbox)) {
816 return SkPDFIndirectReference();
817 }
818
819 SkDynamicMemoryWStream functionCode;
820 switch (state.fType) {
822 linearCode(info, perspectiveInverseOnly, &functionCode);
823 break;
824 case SkShaderBase::GradientType::kRadial:
825 radialCode(info, perspectiveInverseOnly, &functionCode);
826 break;
827 case SkShaderBase::GradientType::kConical: {
828 // The two point radial gradient further references state.fInfo
829 // in translating from x, y coordinates to the t parameter. So, we have
830 // to transform the points and radii according to the calculated matrix.
832 SkMatrix inverseMapperMatrix;
833 if (!mapperMatrix.invert(&inverseMapperMatrix)) {
834 return SkPDFIndirectReference();
835 }
836 inverseMapperMatrix.mapPoints(infoCopy.fPoint, 2);
837 infoCopy.fRadius[0] = inverseMapperMatrix.mapRadius(info.fRadius[0]);
838 infoCopy.fRadius[1] = inverseMapperMatrix.mapRadius(info.fRadius[1]);
839 twoPointConicalCode(infoCopy, perspectiveInverseOnly, &functionCode);
840 } break;
841 case SkShaderBase::GradientType::kSweep:
842 sweepCode(info, perspectiveInverseOnly, &functionCode);
843 break;
844 default:
845 SkASSERT(false);
846 }
847 pdfShader->insertObject(
848 "Domain", SkPDFMakeArray(bbox.left(), bbox.right(), bbox.top(), bbox.bottom()));
849
850 auto domain = SkPDFMakeArray(bbox.left(), bbox.right(), bbox.top(), bbox.bottom());
851 std::unique_ptr<SkPDFArray> rangeObject = SkPDFMakeArray(0, 1, 0, 1, 0, 1);
852 pdfShader->insertRef("Function",
853 make_ps_function(functionCode.detachAsStream(), std::move(domain),
854 std::move(rangeObject), doc));
855 }
856
857 pdfShader->insertInt("ShadingType", SkToS32(shadingType));
858 pdfShader->insertName("ColorSpace", "DeviceRGB");
859
860 SkPDFDict pdfFunctionShader("Pattern");
861 pdfFunctionShader.insertInt("PatternType", 2);
862 pdfFunctionShader.insertObject("Matrix", SkPDFUtils::MatrixToArray(finalMatrix));
863 pdfFunctionShader.insertObject("Shading", std::move(pdfShader));
864 return doc->emit(pdfFunctionShader);
865}
static void radialCode(const SkShaderBase::GradientInfo &info, const SkMatrix &perspectiveRemover, SkDynamicMemoryWStream *function)
static std::unique_ptr< SkPDFDict > gradientStitchCode(const SkShaderBase::GradientInfo &info)
static void sweepCode(const SkShaderBase::GradientInfo &info, const SkMatrix &perspectiveRemover, SkDynamicMemoryWStream *function)
static void linearCode(const SkShaderBase::GradientInfo &info, const SkMatrix &perspectiveRemover, SkDynamicMemoryWStream *function)
static bool split_perspective(const SkMatrix in, SkMatrix *affine, SkMatrix *perspectiveInverse)
static void twoPointConicalCode(const SkShaderBase::GradientInfo &info, const SkMatrix &perspectiveRemover, SkDynamicMemoryWStream *function)
static SkPDFIndirectReference make_ps_function(std::unique_ptr< SkStreamAsset > psCode, std::unique_ptr< SkPDFArray > domain, std::unique_ptr< SkPDFObject > range, SkPDFDocument *doc)
static void unit_to_points_matrix(const SkPoint pts[2], SkMatrix *matrix)
static void FixUpRadius(const SkPoint &p1, SkScalar &r1, const SkPoint &p2, SkScalar &r2)
#define SK_Scalar1
Definition: SkScalar.h:18
constexpr int32_t SkToS32(S x)
Definition: SkTo.h:25
std::unique_ptr< SkStreamAsset > detachAsStream()
Definition: SkStream.cpp:876
SkScalar mapRadius(SkScalar radius) const
Definition: SkMatrix.cpp:1170
void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
Definition: SkMatrix.cpp:770
bool invert(SkMatrix *inverse) const
Definition: SkMatrix.h:1206
SkMatrix & preConcat(const SkMatrix &other)
Definition: SkMatrix.cpp:674
SkPDFIndirectReference emit(const SkPDFObject &, SkPDFIndirectReference)
static constexpr skcms_TransferFunction kLinear
Definition: SkColorSpace.h:51
std::unique_ptr< SkPDFArray > MatrixToArray(const SkMatrix &matrix)
Definition: SkPDFUtils.cpp:67
bool InverseTransformBBox(const SkMatrix &matrix, SkRect *bbox)
Definition: SkPDFUtils.cpp:318
float fX
x-axis value
Definition: SkPoint_impl.h:164
constexpr float y() const
Definition: SkPoint_impl.h:187
constexpr float x() const
Definition: SkPoint_impl.h:181
constexpr float left() const
Definition: SkRect.h:734
constexpr float top() const
Definition: SkRect.h:741
constexpr float right() const
Definition: SkRect.h:748
void set(const SkIRect &src)
Definition: SkRect.h:849
constexpr float bottom() const
Definition: SkRect.h:755

◆ make_key()

static SkPDFGradientShader::Key make_key ( const SkShader shader,
const SkMatrix canvasTransform,
const SkIRect bbox 
)
static

Definition at line 987 of file SkPDFGradientShader.cpp.

989 {
992 {0, nullptr, nullptr, {{0, 0}, {0, 0}}, {0, 0}, SkTileMode::kClamp, 0},
993 nullptr,
994 nullptr,
995 canvasTransform,
997 bbox, 0};
998 key.fType = as_SB(shader)->asGradient(&key.fInfo);
1000 SkASSERT(key.fInfo.fColorCount > 0);
1001 key.fColors.reset(new SkColor[key.fInfo.fColorCount]);
1002 key.fStops.reset(new SkScalar[key.fInfo.fColorCount]);
1003 key.fInfo.fColors = key.fColors.get();
1004 key.fInfo.fColorOffsets = key.fStops.get();
1005 as_SB(shader)->asGradient(&key.fInfo);
1006 key.fHash = hash(key);
1007 return key;
1008}
SkShaderBase * as_SB(SkShader *shader)
Definition: SkShaderBase.h:412
virtual GradientType asGradient(GradientInfo *info=nullptr, SkMatrix *localMatrix=nullptr) const
Definition: SkShaderBase.h:255
SkMatrix GetShaderLocalMatrix(const SkShader *shader)
Definition: SkPDFUtils.h:129

◆ make_ps_function()

static SkPDFIndirectReference make_ps_function ( std::unique_ptr< SkStreamAsset psCode,
std::unique_ptr< SkPDFArray domain,
std::unique_ptr< SkPDFObject range,
SkPDFDocument doc 
)
static

Definition at line 683 of file SkPDFGradientShader.cpp.

686 {
687 std::unique_ptr<SkPDFDict> dict = SkPDFMakeDict();
688 dict->insertInt("FunctionType", 4);
689 dict->insertObject("Domain", std::move(domain));
690 dict->insertObject("Range", std::move(range));
691 return SkPDFStreamOut(std::move(dict), std::move(psCode), doc);
692}

◆ radialCode()

static void radialCode ( const SkShaderBase::GradientInfo info,
const SkMatrix perspectiveRemover,
SkDynamicMemoryWStream function 
)
static

Definition at line 482 of file SkPDFGradientShader.cpp.

484 {
485 function->writeText("{");
486
487 apply_perspective_to_coordinates(perspectiveRemover, function);
488
489 // Find the distance from the origin.
490 function->writeText("dup " // x y y
491 "mul " // x y^2
492 "exch " // y^2 x
493 "dup " // y^2 x x
494 "mul " // y^2 x^2
495 "add " // y^2+x^2
496 "sqrt\n"); // sqrt(y^2+x^2)
497
500 function->writeText("}");
501}

◆ split_perspective()

static bool split_perspective ( const SkMatrix  in,
SkMatrix affine,
SkMatrix perspectiveInverse 
)
static

Definition at line 647 of file SkPDFGradientShader.cpp.

648 {
649 const SkScalar p2 = in[SkMatrix::kMPersp2];
650
651 if (SkScalarNearlyZero(p2)) {
652 return false;
653 }
654
655 const SkScalar zero = SkIntToScalar(0);
656 const SkScalar one = SkIntToScalar(1);
657
658 const SkScalar sx = in[SkMatrix::kMScaleX];
659 const SkScalar kx = in[SkMatrix::kMSkewX];
660 const SkScalar tx = in[SkMatrix::kMTransX];
661 const SkScalar ky = in[SkMatrix::kMSkewY];
662 const SkScalar sy = in[SkMatrix::kMScaleY];
663 const SkScalar ty = in[SkMatrix::kMTransY];
664 const SkScalar p0 = in[SkMatrix::kMPersp0];
665 const SkScalar p1 = in[SkMatrix::kMPersp1];
666
667 // Perspective matrix would be:
668 // 1 0 0
669 // 0 1 0
670 // p0 p1 p2
671 // But we need the inverse of persp.
672 perspectiveInverse->setAll(one, zero, zero,
673 zero, one, zero,
674 -p0/p2, -p1/p2, 1/p2);
675
676 affine->setAll(sx - p0 * tx / p2, kx - p1 * tx / p2, tx / p2,
677 ky - p0 * ty / p2, sy - p1 * ty / p2, ty / p2,
678 zero, zero, one);
679
680 return true;
681}
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkScalar.h:101
static constexpr int kMScaleX
horizontal scale factor
Definition: SkMatrix.h:353
static constexpr int kMTransY
vertical translation
Definition: SkMatrix.h:358
SkMatrix & setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar persp0, SkScalar persp1, SkScalar persp2)
Definition: SkMatrix.h:562
static constexpr int kMTransX
horizontal translation
Definition: SkMatrix.h:355
static constexpr int kMSkewY
vertical skew factor
Definition: SkMatrix.h:356
static constexpr int kMScaleY
vertical scale factor
Definition: SkMatrix.h:357
static constexpr int kMSkewX
horizontal skew factor
Definition: SkMatrix.h:354

◆ sweepCode()

static void sweepCode ( const SkShaderBase::GradientInfo info,
const SkMatrix perspectiveRemover,
SkDynamicMemoryWStream function 
)
static

Definition at line 619 of file SkPDFGradientShader.cpp.

621 {
622 // TODO: Correctly draw tilemode_gradient, requires access to the "bias" and "scale"
623 function->writeText("{exch atan 360 div\n");
626 function->writeText("}");
627}

◆ tileModeCode()

static void tileModeCode ( SkTileMode  mode,
SkDynamicMemoryWStream result 
)
static

Definition at line 395 of file SkPDFGradientShader.cpp.

395 {
396 if (mode == SkTileMode::kRepeat) {
397 result->writeText("dup truncate sub\n"); // Get the fractional part.
398 result->writeText("dup 0 le {1 add} if\n"); // Map (-1,0) => (0,1)
399 return;
400 }
401
402 if (mode == SkTileMode::kMirror) {
403 // In Preview 11.0 (1033.3) `a n mod r eq` (with a and n both integers, r integer or real)
404 // early aborts the function when false would be put on the stack.
405 // Work around this by re-writing `t 2 mod 1 eq` as `t 2 mod 0 gt`.
406
407 // Map t mod 2 into [0, 1, 1, 0].
408 // Code Stack t
409 result->writeText("abs " // +t
410 "dup " // +t.s +t.s
411 "truncate " // +t.s +t
412 "dup " // +t.s +t +t
413 "cvi " // +t.s +t +T
414 "2 mod " // +t.s +t (+T mod 2)
415 /*"1 eq "*/ "0 gt " // +t.s +t true|false
416 "3 1 roll " // true|false +t.s +t
417 "sub " // true|false 0.s
418 "exch " // 0.s true|false
419 "{1 exch sub} if\n"); // 1 - 0.s|0.s
420 }
421}
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition: switches.h:228

◆ twoPointConicalCode()

static void twoPointConicalCode ( const SkShaderBase::GradientInfo info,
const SkMatrix perspectiveRemover,
SkDynamicMemoryWStream function 
)
static

Definition at line 506 of file SkPDFGradientShader.cpp.

508 {
509 SkScalar dx = info.fPoint[1].fX - info.fPoint[0].fX;
510 SkScalar dy = info.fPoint[1].fY - info.fPoint[0].fY;
511 SkScalar r0 = info.fRadius[0];
512 SkScalar dr = info.fRadius[1] - info.fRadius[0];
513 SkScalar a = dx * dx + dy * dy - dr * dr;
514
515 // First compute t, if the pixel falls outside the cone, then we'll end
516 // with 'false' on the stack, otherwise we'll push 'true' with t below it
517
518 // We start with a stack of (x y), copy it and then consume one copy in
519 // order to calculate b and the other to calculate c.
520 function->writeText("{");
521
522 apply_perspective_to_coordinates(perspectiveRemover, function);
523
524 function->writeText("2 copy ");
525
526 // Calculate b and b^2; b = -2 * (y * dy + x * dx + r0 * dr).
528 function->writeText(" mul exch ");
530 function->writeText(" mul add ");
532 function->writeText(" add -2 mul dup dup mul\n");
533
534 // c = x^2 + y^2 + radius0^2
535 function->writeText("4 2 roll dup mul exch dup mul add ");
537 function->writeText(" sub dup 4 1 roll\n");
538
539 // Contents of the stack at this point: c, b, b^2, c
540
541 // if a = 0, then we collapse to a simpler linear case
542 if (a == 0) {
543
544 // t = -c/b
545 function->writeText("pop pop div neg dup ");
546
547 // compute radius(t)
549 function->writeText(" mul ");
551 function->writeText(" add\n");
552
553 // if r(t) < 0, then it's outside the cone
554 function->writeText("0 lt {pop false} {true} ifelse\n");
555
556 } else {
557
558 // quadratic case: the Canvas spec wants the largest
559 // root t for which radius(t) > 0
560
561 // compute the discriminant (b^2 - 4ac)
563 function->writeText(" mul sub dup\n");
564
565 // if d >= 0, proceed
566 function->writeText("0 ge {\n");
567
568 // an intermediate value we'll use to compute the roots:
569 // q = -0.5 * (b +/- sqrt(d))
570 function->writeText("sqrt exch dup 0 lt {exch -1 mul} if");
571 function->writeText(" add -0.5 mul dup\n");
572
573 // first root = q / a
575 function->writeText(" div\n");
576
577 // second root = c / q
578 function->writeText("3 1 roll div\n");
579
580 // put the larger root on top of the stack
581 function->writeText("2 copy gt {exch} if\n");
582
583 // compute radius(t) for larger root
584 function->writeText("dup ");
586 function->writeText(" mul ");
588 function->writeText(" add\n");
589
590 // if r(t) > 0, we have our t, pop off the smaller root and we're done
591 function->writeText(" 0 gt {exch pop true}\n");
592
593 // otherwise, throw out the larger one and try the smaller root
594 function->writeText("{pop dup\n");
596 function->writeText(" mul ");
598 function->writeText(" add\n");
599
600 // if r(t) < 0, push false, otherwise the smaller root is our t
601 function->writeText("0 le {pop false} {true} ifelse\n");
602 function->writeText("} ifelse\n");
603
604 // d < 0, clear the stack and push false
605 function->writeText("} {pop pop pop false} ifelse\n");
606 }
607
608 // if the pixel is in the cone, proceed to compute a color
609 function->writeText("{");
612
613 // otherwise, just write black
614 // TODO: Correctly draw gradients_local_persepective, need to mask out this black
615 // The "gradients" gm works as falls into the 8.7.4.5.4 "Type 3 (Radial) Shadings" case.
616 function->writeText("} {0 0 0} ifelse }");
617}
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
Definition: SkRecords.h:208

◆ unit_to_points_matrix()

static void unit_to_points_matrix ( const SkPoint  pts[2],
SkMatrix matrix 
)
static

Definition at line 57 of file SkPDFGradientShader.cpp.

57 {
58 SkVector vec = pts[1] - pts[0];
59 SkScalar mag = vec.length();
60 SkScalar inv = mag ? SkScalarInvert(mag) : 0;
61
62 vec.scale(inv);
63 matrix->setSinCos(vec.fY, vec.fX);
64 matrix->preScale(mag, mag);
65 matrix->postTranslate(pts[0].fX, pts[0].fY);
66}
static SkM44 inv(const SkM44 &m)
Definition: 3d.cpp:26
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
float length() const
Definition: SkPoint_impl.h:282
void scale(float scale, SkPoint *dst) const
Definition: SkPoint.cpp:17
float fY
y-axis value
Definition: SkPoint_impl.h:165

◆ write_gradient_ranges()

static void write_gradient_ranges ( const SkShaderBase::GradientInfo info,
SkSpan< size_t >  rangeEnds,
bool  top,
bool  first,
SkDynamicMemoryWStream result 
)
static

Definition at line 144 of file SkPDFGradientShader.cpp.

145 {
146 SkASSERT(!rangeEnds.empty());
147
148 size_t rangeEndIndex = rangeEnds[rangeEnds.size() - 1];
149 SkScalar rangeEnd = info.fColorOffsets[rangeEndIndex];
150
151 // Each range check tests 0 < t <= end.
152 if (top) {
153 SkASSERT(first);
154 // t may have been set to 0 to signal that the answer has already been found.
155 result->writeText("dup dup 0 gt exch "); // In Preview 11.0 (1033.3) `0. 0 ne` is true.
157 result->writeText(" le and {\n");
158 } else if (first) {
159 // After the top level check, only t <= end needs to be tested on if (lo) side.
160 result->writeText("dup ");
162 result->writeText(" le {\n");
163 } else {
164 // The else (hi) side.
165 result->writeText("{\n");
166 }
167
168 if (rangeEnds.size() == 1) {
169 // Set the stack to [r g b].
170 size_t rangeBeginIndex = rangeEndIndex - 1;
171 SkScalar rangeBegin = info.fColorOffsets[rangeBeginIndex];
172 SkPDFUtils::AppendScalar(rangeBegin, result);
173 result->writeText(" sub "); // consume t, put t - startOffset on the stack.
174 interpolate_color_code(rangeEnd - rangeBegin,
175 info.fColors[rangeBeginIndex], info.fColors[rangeEndIndex], result);
176 result->writeText("\n");
177 } else {
178 size_t loCount = rangeEnds.size() / 2;
179 SkSpan<size_t> loSpan = rangeEnds.subspan(0, loCount);
180 write_gradient_ranges(info, loSpan, false, true, result);
181
182 SkSpan<size_t> hiSpan = rangeEnds.subspan(loCount, rangeEnds.size() - loCount);
183 write_gradient_ranges(info, hiSpan, false, false, result);
184 }
185
186 if (top) {
187 // Put 0 on the stack for t once here instead of after every call to interpolate_color_code.
188 result->writeText("0} if\n");
189 } else if (first) {
190 result->writeText("}"); // The else (hi) side will come next.
191 } else {
192 result->writeText("} ifelse\n");
193 }
194}
static void interpolate_color_code(SkScalar range, SkColor beginColor, SkColor endColor, SkDynamicMemoryWStream *result)
constexpr SkSpan< T > subspan(size_t offset) const
Definition: SkSpan_impl.h:105
constexpr bool empty() const
Definition: SkSpan_impl.h:96
constexpr size_t size() const
Definition: SkSpan_impl.h:95

Variable Documentation

◆ kColorComponents

const int kColorComponents = 3
static

Definition at line 68 of file SkPDFGradientShader.cpp.