11
11
#include " impeller/entity/content_context.h"
12
12
#include " impeller/entity/entity.h"
13
13
#include " impeller/geometry/path_builder.h"
14
+ #include " impeller/geometry/scalar.h"
14
15
#include " impeller/geometry/vector.h"
15
16
#include " impeller/renderer/render_pass.h"
16
17
#include " impeller/renderer/sampler_library.h"
@@ -284,8 +285,7 @@ const IRect& TextureContents::GetSourceRect() const {
284
285
285
286
SolidStrokeContents::SolidStrokeContents () {
286
287
SetStrokeCap (Cap::kButt );
287
- // TODO(99089): Change this to kMiter once implemented.
288
- SetStrokeJoin (Join::kBevel );
288
+ SetStrokeJoin (Join::kMiter );
289
289
}
290
290
291
291
SolidStrokeContents::~SolidStrokeContents () = default ;
@@ -302,7 +302,8 @@ static VertexBuffer CreateSolidStrokeVertices(
302
302
const Path& path,
303
303
HostBuffer& buffer,
304
304
const SolidStrokeContents::CapProc& cap_proc,
305
- const SolidStrokeContents::JoinProc& join_proc) {
305
+ const SolidStrokeContents::JoinProc& join_proc,
306
+ Scalar miter_limit) {
306
307
using VS = SolidStrokeVertexShader;
307
308
308
309
VertexBufferBuilder<VS::PerVertexData> vtx_builder;
@@ -380,7 +381,7 @@ static VertexBuffer CreateSolidStrokeVertices(
380
381
381
382
// Generate join from the current line to the next line.
382
383
join_proc (vtx_builder, polyline.points [point_i], previous_normal,
383
- normal );
384
+ normal , miter_limit );
384
385
}
385
386
}
386
387
}
@@ -390,7 +391,7 @@ static VertexBuffer CreateSolidStrokeVertices(
390
391
cap_proc (vtx_builder, polyline.points [contour_end_point_i - 1 ], normal );
391
392
} else {
392
393
join_proc (vtx_builder, polyline.points [contour_start_point_i], normal ,
393
- contour_first_normal);
394
+ contour_first_normal, miter_limit );
394
395
}
395
396
}
396
397
@@ -419,8 +420,9 @@ bool SolidStrokeContents::Render(const ContentContext& renderer,
419
420
cmd.label = " SolidStroke" ;
420
421
cmd.pipeline = renderer.GetSolidStrokePipeline (OptionsFromPass (pass));
421
422
cmd.stencil_reference = entity.GetStencilDepth ();
422
- cmd.BindVertices (CreateSolidStrokeVertices (
423
- entity.GetPath (), pass.GetTransientsBuffer (), cap_proc_, join_proc_));
423
+ cmd.BindVertices (
424
+ CreateSolidStrokeVertices (entity.GetPath (), pass.GetTransientsBuffer (),
425
+ cap_proc_, join_proc_, miter_limit_));
424
426
VS::BindFrameInfo (cmd, pass.GetTransientsBuffer ().EmplaceUniform (frame_info));
425
427
VS::BindStrokeInfo (cmd,
426
428
pass.GetTransientsBuffer ().EmplaceUniform (stroke_info));
@@ -438,12 +440,15 @@ Scalar SolidStrokeContents::GetStrokeSize() const {
438
440
return stroke_size_;
439
441
}
440
442
441
- void SolidStrokeContents::SetStrokeMiter (Scalar miter) {
442
- miter_ = miter;
443
+ void SolidStrokeContents::SetStrokeMiter (Scalar miter_limit) {
444
+ if (miter_limit < 0 ) {
445
+ return ; // Skia behaves like this.
446
+ }
447
+ miter_limit_ = miter_limit;
443
448
}
444
449
445
- Scalar SolidStrokeContents::GetStrokeMiter (Scalar miter ) {
446
- return miter_ ;
450
+ Scalar SolidStrokeContents::GetStrokeMiter () {
451
+ return miter_limit_ ;
447
452
}
448
453
449
454
void SolidStrokeContents::SetStrokeCap (Cap cap) {
@@ -484,6 +489,26 @@ SolidStrokeContents::Cap SolidStrokeContents::GetStrokeCap() {
484
489
return cap_;
485
490
}
486
491
492
+ static Scalar CreateBevelAndGetDirection (
493
+ VertexBufferBuilder<SolidStrokeVertexShader::PerVertexData>& vtx_builder,
494
+ const Point & position,
495
+ const Point & start_normal,
496
+ const Point & end_normal) {
497
+ SolidStrokeVertexShader::PerVertexData vtx;
498
+ vtx.vertex_position = position;
499
+ vtx.pen_down = 1.0 ;
500
+ vtx.vertex_normal = {};
501
+ vtx_builder.AppendVertex (vtx);
502
+
503
+ Scalar dir = start_normal.Cross (end_normal) > 0 ? -1 : 1 ;
504
+ vtx.vertex_normal = start_normal * dir;
505
+ vtx_builder.AppendVertex (vtx);
506
+ vtx.vertex_normal = end_normal * dir;
507
+ vtx_builder.AppendVertex (vtx);
508
+
509
+ return dir;
510
+ }
511
+
487
512
void SolidStrokeContents::SetStrokeJoin (Join join) {
488
513
join_ = join;
489
514
@@ -492,23 +517,37 @@ void SolidStrokeContents::SetStrokeJoin(Join join) {
492
517
case Join::kBevel :
493
518
join_proc_ = [](VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
494
519
const Point & position, const Point & start_normal,
495
- const Point & end_normal) {
520
+ const Point & end_normal, Scalar miter_limit) {
521
+ CreateBevelAndGetDirection (vtx_builder, position, start_normal, end_normal);
522
+ };
523
+ break ;
524
+ case Join::kMiter :
525
+ join_proc_ = [](VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
526
+ const Point & position, const Point & start_normal,
527
+ const Point & end_normal, Scalar miter_limit) {
528
+ // 1 for no joint (straight line), 0 for max joint (180 degrees).
529
+ Scalar alignment = (start_normal.Dot (end_normal) + 1 ) / 2 ;
530
+ if (ScalarNearlyEqual (alignment, 1 )) {
531
+ return ;
532
+ }
533
+
534
+ Scalar dir =
535
+ CreateBevelAndGetDirection (vtx_builder, position, start_normal, end_normal);
536
+
537
+ Point miter_point = (start_normal + end_normal) / 2 / alignment;
538
+ if (miter_point.GetDistanceSquared ({0 , 0 }) >
539
+ miter_limit * miter_limit) {
540
+ return ; // Convert to bevel when we exceed the miter limit.
541
+ }
542
+
543
+ // Outer miter point.
496
544
SolidStrokeVertexShader::PerVertexData vtx;
497
545
vtx.vertex_position = position;
498
546
vtx.pen_down = 1.0 ;
499
- vtx.vertex_normal = {};
500
- vtx_builder.AppendVertex (vtx);
501
-
502
- Scalar dir = start_normal.Cross (end_normal) > 0 ? -1 : 1 ;
503
- vtx.vertex_normal = start_normal * dir;
504
- vtx_builder.AppendVertex (vtx);
505
- vtx.vertex_normal = end_normal * dir;
547
+ vtx.vertex_normal = miter_point * dir;
506
548
vtx_builder.AppendVertex (vtx);
507
549
};
508
550
break ;
509
- case Join::kMiter :
510
- FML_DLOG (ERROR) << " Unimplemented." ;
511
- break ;
512
551
case Join::kRound :
513
552
FML_DLOG (ERROR) << " Unimplemented." ;
514
553
break ;
0 commit comments