| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "export.h" |
| #include "helpers.h" |
| #include "wrappers.h" |
| |
| #include "third_party/skia/include/core/SkPoint3.h" |
| #include "third_party/skia/include/core/SkVertices.h" |
| #include "third_party/skia/include/utils/SkShadowUtils.h" |
| #include "third_party/skia/modules/skparagraph/include/Paragraph.h" |
| |
| using namespace skia::textlayout; |
| |
| using namespace Skwasm; |
| |
| namespace { |
| // These numbers have been chosen empirically to give a result closest to the |
| // material spec. |
| // These values are also used by the CanvasKit renderer and the native engine. |
| // See: |
| // flutter/display_list/skia/dl_sk_dispatcher.cc |
| // flutter/lib/web_ui/lib/src/engine/canvaskit/util.dart |
| constexpr SkScalar kShadowAmbientAlpha = 0.039; |
| constexpr SkScalar kShadowSpotAlpha = 0.25; |
| constexpr SkScalar kShadowLightRadius = 1.1; |
| constexpr SkScalar kShadowLightHeight = 600.0; |
| constexpr SkScalar kShadowLightXOffset = 0; |
| constexpr SkScalar kShadowLightYOffset = -450; |
| } // namespace |
| |
| SKWASM_EXPORT void canvas_saveLayer(SkCanvas* canvas, |
| SkRect* rect, |
| SkPaint* paint, |
| SkImageFilter* backdrop) { |
| canvas->saveLayer(SkCanvas::SaveLayerRec(rect, paint, backdrop, 0)); |
| } |
| |
| SKWASM_EXPORT void canvas_save(SkCanvas* canvas) { |
| canvas->save(); |
| } |
| |
| SKWASM_EXPORT void canvas_restore(SkCanvas* canvas) { |
| canvas->restore(); |
| } |
| |
| SKWASM_EXPORT void canvas_restoreToCount(SkCanvas* canvas, int count) { |
| canvas->restoreToCount(count); |
| } |
| |
| SKWASM_EXPORT int canvas_getSaveCount(SkCanvas* canvas) { |
| return canvas->getSaveCount(); |
| } |
| |
| SKWASM_EXPORT void canvas_translate(SkCanvas* canvas, |
| SkScalar dx, |
| SkScalar dy) { |
| canvas->translate(dx, dy); |
| } |
| |
| SKWASM_EXPORT void canvas_scale(SkCanvas* canvas, SkScalar sx, SkScalar sy) { |
| canvas->scale(sx, sy); |
| } |
| |
| SKWASM_EXPORT void canvas_rotate(SkCanvas* canvas, SkScalar degrees) { |
| canvas->rotate(degrees); |
| } |
| |
| SKWASM_EXPORT void canvas_skew(SkCanvas* canvas, SkScalar sx, SkScalar sy) { |
| canvas->skew(sx, sy); |
| } |
| |
| SKWASM_EXPORT void canvas_transform(SkCanvas* canvas, const SkM44* matrix44) { |
| canvas->concat(*matrix44); |
| } |
| |
| SKWASM_EXPORT void canvas_clipRect(SkCanvas* canvas, |
| const SkRect* rect, |
| SkClipOp op, |
| bool antialias) { |
| canvas->clipRect(*rect, op, antialias); |
| } |
| |
| SKWASM_EXPORT void canvas_clipRRect(SkCanvas* canvas, |
| const SkScalar* rrectValues, |
| bool antialias) { |
| canvas->clipRRect(createRRect(rrectValues), antialias); |
| } |
| |
| SKWASM_EXPORT void canvas_clipPath(SkCanvas* canvas, |
| SkPath* path, |
| bool antialias) { |
| canvas->clipPath(*path, antialias); |
| } |
| |
| SKWASM_EXPORT void canvas_drawColor(SkCanvas* canvas, |
| SkColor color, |
| SkBlendMode blendMode) { |
| canvas->drawColor(color, blendMode); |
| } |
| |
| SKWASM_EXPORT void canvas_drawLine(SkCanvas* canvas, |
| SkScalar x1, |
| SkScalar y1, |
| SkScalar x2, |
| SkScalar y2, |
| SkPaint* paint) { |
| canvas->drawLine(x1, y1, x2, y2, *paint); |
| } |
| |
| SKWASM_EXPORT void canvas_drawPaint(SkCanvas* canvas, SkPaint* paint) { |
| canvas->drawPaint(*paint); |
| } |
| |
| SKWASM_EXPORT void canvas_drawRect(SkCanvas* canvas, |
| SkRect* rect, |
| SkPaint* paint) { |
| canvas->drawRect(*rect, *paint); |
| } |
| |
| SKWASM_EXPORT void canvas_drawRRect(SkCanvas* canvas, |
| const SkScalar* rrectValues, |
| SkPaint* paint) { |
| canvas->drawRRect(createRRect(rrectValues), *paint); |
| } |
| |
| SKWASM_EXPORT void canvas_drawDRRect(SkCanvas* canvas, |
| const SkScalar* outerRrectValues, |
| const SkScalar* innerRrectValues, |
| SkPaint* paint) { |
| canvas->drawDRRect(createRRect(outerRrectValues), |
| createRRect(innerRrectValues), *paint); |
| } |
| |
| SKWASM_EXPORT void canvas_drawOval(SkCanvas* canvas, |
| const SkRect* rect, |
| SkPaint* paint) { |
| canvas->drawOval(*rect, *paint); |
| } |
| |
| SKWASM_EXPORT void canvas_drawCircle(SkCanvas* canvas, |
| SkScalar x, |
| SkScalar y, |
| SkScalar radius, |
| SkPaint* paint) { |
| canvas->drawCircle(x, y, radius, *paint); |
| } |
| |
| SKWASM_EXPORT void canvas_drawArc(SkCanvas* canvas, |
| const SkRect* rect, |
| SkScalar startAngleDegrees, |
| SkScalar sweepAngleDegrees, |
| bool useCenter, |
| SkPaint* paint) { |
| canvas->drawArc(*rect, startAngleDegrees, sweepAngleDegrees, useCenter, |
| *paint); |
| } |
| |
| SKWASM_EXPORT void canvas_drawPath(SkCanvas* canvas, |
| SkPath* path, |
| SkPaint* paint) { |
| canvas->drawPath(*path, *paint); |
| } |
| |
| SKWASM_EXPORT void canvas_drawShadow(SkCanvas* canvas, |
| SkPath* path, |
| SkScalar elevation, |
| SkScalar devicePixelRatio, |
| SkColor color, |
| bool transparentOccluder) { |
| SkColor inAmbient = |
| SkColorSetA(color, kShadowAmbientAlpha * SkColorGetA(color)); |
| SkColor inSpot = SkColorSetA(color, kShadowSpotAlpha * SkColorGetA(color)); |
| SkColor outAmbient; |
| SkColor outSpot; |
| SkShadowUtils::ComputeTonalColors(inAmbient, inSpot, &outAmbient, &outSpot); |
| uint32_t flags = transparentOccluder |
| ? SkShadowFlags::kTransparentOccluder_ShadowFlag |
| : SkShadowFlags::kNone_ShadowFlag; |
| flags |= SkShadowFlags::kDirectionalLight_ShadowFlag; |
| SkShadowUtils::DrawShadow( |
| canvas, *path, SkPoint3::Make(0.0f, 0.0f, elevation * devicePixelRatio), |
| SkPoint3::Make(kShadowLightXOffset, kShadowLightYOffset, |
| kShadowLightHeight * devicePixelRatio), |
| devicePixelRatio * kShadowLightRadius, outAmbient, outSpot, flags); |
| } |
| |
| SKWASM_EXPORT void canvas_drawParagraph(SkCanvas* canvas, |
| Paragraph* paragraph, |
| SkScalar x, |
| SkScalar y) { |
| paragraph->paint(canvas, x, y); |
| } |
| |
| SKWASM_EXPORT void canvas_drawPicture(SkCanvas* canvas, SkPicture* picture) { |
| canvas->drawPicture(picture); |
| } |
| |
| SKWASM_EXPORT void canvas_drawImage(SkCanvas* canvas, |
| SkImage* image, |
| SkScalar offsetX, |
| SkScalar offsetY, |
| SkPaint* paint, |
| FilterQuality quality) { |
| canvas->drawImage(image, offsetX, offsetY, samplingOptionsForQuality(quality), |
| paint); |
| } |
| |
| SKWASM_EXPORT void canvas_drawImageRect(SkCanvas* canvas, |
| SkImage* image, |
| SkRect* sourceRect, |
| SkRect* destRect, |
| SkPaint* paint, |
| FilterQuality quality) { |
| canvas->drawImageRect(image, *sourceRect, *destRect, |
| samplingOptionsForQuality(quality), paint, |
| SkCanvas::kStrict_SrcRectConstraint); |
| } |
| |
| SKWASM_EXPORT void canvas_drawImageNine(SkCanvas* canvas, |
| SkImage* image, |
| SkIRect* centerRect, |
| SkRect* destinationRect, |
| SkPaint* paint, |
| FilterQuality quality) { |
| canvas->drawImageNine(image, *centerRect, *destinationRect, |
| filterModeForQuality(quality), paint); |
| } |
| |
| SKWASM_EXPORT void canvas_drawVertices(SkCanvas* canvas, |
| SkVertices* vertices, |
| SkBlendMode mode, |
| SkPaint* paint) { |
| canvas->drawVertices(sk_ref_sp<SkVertices>(vertices), mode, *paint); |
| } |
| |
| SKWASM_EXPORT void canvas_drawPoints(SkCanvas* canvas, |
| SkCanvas::PointMode mode, |
| SkPoint* points, |
| int pointCount, |
| SkPaint* paint) { |
| canvas->drawPoints(mode, pointCount, points, *paint); |
| } |
| |
| SKWASM_EXPORT void canvas_drawAtlas(SkCanvas* canvas, |
| SkImage* atlas, |
| SkRSXform* transforms, |
| SkRect* rects, |
| SkColor* colors, |
| int spriteCount, |
| SkBlendMode mode, |
| SkRect* cullRect, |
| SkPaint* paint) { |
| canvas->drawAtlas( |
| atlas, transforms, rects, colors, spriteCount, mode, |
| SkSamplingOptions{SkFilterMode::kLinear, SkMipmapMode::kNone}, cullRect, |
| paint); |
| } |
| |
| SKWASM_EXPORT void canvas_getTransform(SkCanvas* canvas, SkM44* outTransform) { |
| *outTransform = canvas->getLocalToDevice(); |
| } |
| |
| SKWASM_EXPORT void canvas_getLocalClipBounds(SkCanvas* canvas, |
| SkRect* outRect) { |
| *outRect = canvas->getLocalClipBounds(); |
| } |
| |
| SKWASM_EXPORT void canvas_getDeviceClipBounds(SkCanvas* canvas, |
| SkIRect* outRect) { |
| *outRect = canvas->getDeviceClipBounds(); |
| } |