291 {
292 if (inComponents.size() > 4) {
294 maskPos.endOffset()),
295 "too many components in swizzle mask");
296 return nullptr;
297 }
298
300 context.fErrors->error(maskPos,
"invalid swizzle mask '" +
MaskString(inComponents) +
"'");
301 return nullptr;
302 }
303
304 const Type& baseType =
base->type().scalarTypeForLiteral();
305
306 if (!baseType.isVector() && !baseType.isScalar()) {
307 context.fErrors->error(
pos,
"cannot swizzle value of type '" +
308 baseType.displayName() + "'");
309 return nullptr;
310 }
311
313 bool foundXYZW = false;
314 for (int i = 0; i < inComponents.size(); ++i) {
315 switch (inComponents[i]) {
318
319 break;
324 foundXYZW = true;
326 break;
331 foundXYZW = true;
332 if (baseType.columns() >= 2) {
334 break;
335 }
336 [[fallthrough]];
341 foundXYZW = true;
342 if (baseType.columns() >= 3) {
344 break;
345 }
346 [[fallthrough]];
351 foundXYZW = true;
352 if (baseType.columns() >= 4) {
354 break;
355 }
356 [[fallthrough]];
357 default:
358
360 maskPos.startOffset() + i + 1),
363 return nullptr;
364 }
365 }
366
367 if (!foundXYZW) {
368 context.fErrors->error(maskPos, "swizzle must refer to base expression");
369 return nullptr;
370 }
371
372
373 base = baseType.coerceExpression(std::move(
base), context);
375 return nullptr;
376 }
377
378
379
380
381
382
383 std::unique_ptr<Expression> expr =
Swizzle::Make(context,
pos, std::move(
base), maskComponents);
384
385
386 if (maskComponents.size() == inComponents.size()) {
387 return expr;
388 }
389
390
391
392
393
394
395
396
397 ExpressionArray constructorArgs;
398 constructorArgs.reserve_exact(3);
399 constructorArgs.push_back(std::move(expr));
400
401
402
403
404
405
406 const Type* scalarType = &baseType.componentType();
408 int maskFieldIdx = 0;
409 int constantFieldIdx = maskComponents.
size();
410 int constantZeroIdx = -1, constantOneIdx = -1;
411
412 for (int i = 0; i < inComponents.size(); i++) {
413 switch (inComponents[i]) {
415 if (constantZeroIdx == -1) {
416
418 constantZeroIdx = constantFieldIdx++;
419 }
420 swizzleComponents.push_back(constantZeroIdx);
421 break;
423 if (constantOneIdx == -1) {
424
426 constantOneIdx = constantFieldIdx++;
427 }
428 swizzleComponents.push_back(constantOneIdx);
429 break;
430 default:
431
432 swizzleComponents.push_back(maskFieldIdx++);
433 break;
434 }
435 }
436
438 scalarType->toCompound(context, constantFieldIdx, 1),
439 std::move(constructorArgs));
440
441
443}
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type &type, ExpressionArray args)
static std::unique_ptr< Literal > Make(Position pos, double value, const Type *type)
static Position Range(int startOffset, int endOffset)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, std::unique_ptr< Expression > expr, ComponentArray inComponents)
static std::string MaskString(const ComponentArray &inComponents)
std::string printf(const char *fmt,...) SK_PRINTF_LIKE(1
skia_private::STArray< 4, int8_t > ComponentArray
static bool validate_swizzle_domain(const ComponentArray &fields)
static char mask_char(int8_t component)