MCPcopy Create free account
hub / github.com/Tencent/tgfx / GradientFunctionCode

Function GradientFunctionCode

src/pdf/PDFGradientShader.cpp:301–354  ·  view source on GitHub ↗

Generate Type 4 function code to map t to the passed gradient, clamping at the ends. The types integer, real, and boolean are available. There are no string, array, procedure, variable, or name types available. The generated code will be of the following form with all values hard coded. if (t <= 0) { ret = color[0]; t = 0; } if (t > 0 && t <= stop[4]) { if (t <= stop[2

Source from the content-addressed store, hash-verified

299 0 gt {1 1 1} if
300 */
301void GradientFunctionCode(const GradientInfo& info,
302 const std::shared_ptr<MemoryWriteStream>& result) {
303 // While looking for a hit the stack is [t]. After finding a hit the stack is [r g b 0]. The 0 is
304 // consumed just before returning.
305
306 // The initial range has no previous and contains a solid color.
307 // Any t <= 0 will be handled by this initial range, so later t == 0 indicates a hit was found.
308 result->writeText("dup 0 le {pop ");
309 PDFUtils::AppendColorComponent(static_cast<uint8_t>(info.colors[0].red * 255), result);
310 result->writeText(" ");
311 PDFUtils::AppendColorComponent(static_cast<uint8_t>(info.colors[0].green * 255), result);
312 result->writeText(" ");
313 PDFUtils::AppendColorComponent(static_cast<uint8_t>(info.colors[0].blue * 255), result);
314 result->writeText(" 0} if\n");
315
316 // Optimize out ranges which don't make any visual difference.
317 std::vector<size_t> rangeEnds(info.colors.size());
318 size_t rangeEndsCount = 0;
319 for (size_t i = 1; i < info.colors.size(); ++i) {
320 // Ignoring the alpha, is this range the same solid color as the next range?
321 // This optimizes gradients where sometimes only the color or only the alpha is changing.
322 auto eqIgnoringAlpha = [](Color a, Color b) {
323 return FloatNearlyEqual(a.red, b.red) && FloatNearlyEqual(a.green, b.green) &&
324 FloatNearlyEqual(a.blue, b.blue);
325 };
326
327 bool constantColorBothSides =
328 eqIgnoringAlpha(info.colors[i - 1], info.colors[i]) && // This range is a solid color.
329 i != info.colors.size() - 1 && // This is not the last range.
330 eqIgnoringAlpha(info.colors[i], info.colors[i + 1]); // Next range is same solid color.
331
332 // Does this range have zero size?
333 bool degenerateRange = info.positions[i - 1] == info.positions[i];
334
335 if (!degenerateRange && !constantColorBothSides) {
336 rangeEnds[rangeEndsCount] = i;
337 ++rangeEndsCount;
338 }
339 }
340
341 // If a cap on depth is needed, loop here.
342 std::vector<size_t> range(rangeEnds.begin(),
343 rangeEnds.begin() + static_cast<std::ptrdiff_t>(rangeEndsCount));
344 WriteGradientRanges(info, range, true, true, result);
345
346 // Clamp the final color.
347 result->writeText("0 gt {");
348 PDFUtils::AppendColorComponent(static_cast<uint8_t>(info.colors.back().red * 255), result);
349 result->writeText(" ");
350 PDFUtils::AppendColorComponent(static_cast<uint8_t>(info.colors.back().green * 255), result);
351 result->writeText(" ");
352 PDFUtils::AppendColorComponent(static_cast<uint8_t>(info.colors.back().blue * 255), result);
353 result->writeText("} if\n");
354}
355
356void LinearCode(const GradientInfo& info, const Matrix& /*perspectiveRemover*/,
357 const std::shared_ptr<MemoryWriteStream>& function) {

Callers 3

LinearCodeFunction · 0.85
RadialCodeFunction · 0.85
TwoPointConicalCodeFunction · 0.85

Calls 5

FloatNearlyEqualFunction · 0.85
WriteGradientRangesFunction · 0.85
writeTextMethod · 0.80
sizeMethod · 0.45
beginMethod · 0.45

Tested by

no test coverage detected