@@ -293,50 +293,120 @@ const Color& SolidStrokeContents::GetColor() const {
293293 return color_;
294294}
295295
296+ static void CreateCap (
297+ VertexBufferBuilder<SolidStrokeVertexShader::PerVertexData>& vtx_builder,
298+ const Point& position,
299+ const Point& normal) {}
300+
301+ static void CreateJoin (
302+ VertexBufferBuilder<SolidStrokeVertexShader::PerVertexData>& vtx_builder,
303+ const Point& position,
304+ const Point& start_normal,
305+ const Point& end_normal) {
306+ SolidStrokeVertexShader::PerVertexData vtx;
307+ vtx.vertex_position = position;
308+ vtx.pen_down = 1.0 ;
309+ vtx.vertex_normal = {};
310+ vtx_builder.AppendVertex (vtx);
311+
312+ // A simple bevel join to start with.
313+ Scalar dir = start_normal.Cross (end_normal) > 0 ? -1 : 1 ;
314+ vtx.vertex_normal = start_normal * dir;
315+ vtx_builder.AppendVertex (vtx);
316+ vtx.vertex_normal = end_normal * dir;
317+ vtx_builder.AppendVertex (vtx);
318+ }
319+
296320static VertexBuffer CreateSolidStrokeVertices (const Path& path,
297321 HostBuffer& buffer) {
298322 using VS = SolidStrokeVertexShader;
299323
300324 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
301325 auto polyline = path.CreatePolyline ();
302326
303- for (size_t i = 0 , polyline_size = polyline.points .size (); i < polyline_size;
304- i++) {
305- const auto is_last_point = i == polyline_size - 1 ;
306-
307- const auto & p1 = polyline.points [i];
308- const auto & p2 =
309- is_last_point ? polyline.points [i - 1 ] : polyline.points [i + 1 ];
310-
311- const auto diff = p2 - p1;
312-
313- const Scalar direction = is_last_point ? -1.0 : 1.0 ;
327+ size_t point_i = 0 ;
328+ if (polyline.points .size () < 2 ) {
329+ return {}; // Nothing to render.
330+ }
314331
315- const auto normal =
316- Point{-diff.y * direction, diff.x * direction}.Normalize ();
332+ VS::PerVertexData vtx;
333+
334+ // Cursor state.
335+ Point direction;
336+ Point normal;
337+ Point previous_normal; // Used for computing joins.
338+ auto compute_normals = [&](size_t point_i) {
339+ previous_normal = normal;
340+ direction =
341+ (polyline.points [point_i] - polyline.points [point_i - 1 ]).Normalize ();
342+ normal = {-direction.y , direction.x };
343+ };
344+ compute_normals (1 );
345+
346+ // Break state.
347+ auto breaks_it = polyline.breaks .begin ();
348+ size_t break_end =
349+ breaks_it != polyline.breaks .end () ? *breaks_it : polyline.points .size ();
350+
351+ while (point_i < polyline.points .size ()) {
352+ if (point_i > 0 ) {
353+ compute_normals (point_i);
354+
355+ // This branch only executes when we've just finished drawing a contour
356+ // and are switching to a new one.
357+ // We're drawing a triangle strip, so we need to "pick up the pen" by
358+ // appending transparent vertices between the end of the previous contour
359+ // and the beginning of the new contour.
360+ vtx.vertex_position = polyline.points [point_i - 1 ];
361+ vtx.vertex_normal = {};
362+ vtx.pen_down = 0.0 ;
363+ vtx_builder.AppendVertex (vtx);
364+ vtx.vertex_position = polyline.points [point_i];
365+ vtx_builder.AppendVertex (vtx);
366+ }
317367
318- VS::PerVertexData vtx;
319- vtx.vertex_position = p1;
320- auto pen_down =
321- polyline.breaks .find (i) == polyline.breaks .end () ? 1.0 : 0.0 ;
368+ // Generate start cap.
369+ CreateCap (vtx_builder, polyline.points [point_i], -direction);
370+
371+ // Generate contour geometry.
372+ size_t contour_point_i = 0 ;
373+ while (point_i < break_end) {
374+ if (contour_point_i > 0 ) {
375+ if (contour_point_i > 1 ) {
376+ // Generate join from the previous line to the current line.
377+ CreateJoin (vtx_builder, polyline.points [point_i - 1 ], previous_normal,
378+ normal);
379+ } else {
380+ compute_normals (point_i);
381+ }
382+
383+ // Generate line rect.
384+ vtx.vertex_position = polyline.points [point_i - 1 ];
385+ vtx.pen_down = 1.0 ;
386+ vtx.vertex_normal = normal;
387+ vtx_builder.AppendVertex (vtx);
388+ vtx.vertex_normal = -normal;
389+ vtx_builder.AppendVertex (vtx);
390+ vtx.vertex_position = polyline.points [point_i];
391+ vtx.vertex_normal = normal;
392+ vtx_builder.AppendVertex (vtx);
393+ vtx.vertex_normal = -normal;
394+ vtx_builder.AppendVertex (vtx);
322395
323- vtx.vertex_normal = normal;
324- vtx.pen_down = pen_down;
325- vtx_builder.AppendVertex (vtx);
396+ compute_normals (point_i + 1 );
397+ }
326398
327- vtx. vertex_normal = -normal ;
328- vtx. pen_down = pen_down ;
329- vtx_builder. AppendVertex (vtx);
399+ ++contour_point_i ;
400+ ++point_i ;
401+ }
330402
331- // Put the pen down again for the next contour.
332- if (!pen_down) {
333- vtx.vertex_normal = normal;
334- vtx.pen_down = 1.0 ;
335- vtx_builder.AppendVertex (vtx);
403+ // Generate end cap.
404+ CreateCap (vtx_builder, polyline.points [point_i - 1 ], -direction);
336405
337- vtx.vertex_normal = -normal;
338- vtx.pen_down = 1.0 ;
339- vtx_builder.AppendVertex (vtx);
406+ if (break_end < polyline.points .size ()) {
407+ ++breaks_it;
408+ break_end = breaks_it != polyline.breaks .end () ? *breaks_it
409+ : polyline.points .size ();
340410 }
341411 }
342412
@@ -384,6 +454,30 @@ Scalar SolidStrokeContents::GetStrokeSize() const {
384454 return stroke_size_;
385455}
386456
457+ void SolidStrokeContents::SetStrokeMiter (Scalar miter) {
458+ miter_ = miter;
459+ }
460+
461+ Scalar SolidStrokeContents::GetStrokeMiter (Scalar miter) {
462+ return miter_;
463+ }
464+
465+ void SolidStrokeContents::SetStrokeCap (Cap cap) {
466+ cap_ = cap;
467+ }
468+
469+ SolidStrokeContents::Cap SolidStrokeContents::GetStrokeCap () {
470+ return cap_;
471+ }
472+
473+ void SolidStrokeContents::SetStrokeJoin (Join join) {
474+ join_ = join;
475+ }
476+
477+ SolidStrokeContents::Join SolidStrokeContents::GetStrokeJoin () {
478+ return join_;
479+ }
480+
387481/* ******************************************************************************
388482 ******* ClipContents
389483 ******************************************************************************/
0 commit comments