774 {
775 if (!fText->fHasFill && !fText->fHasStroke) {
776 return;
777 }
778
779 if (fText.hasChanged()) {
780 this->reshape();
781 }
782
783 if (fFragments.empty()) {
784 return;
785 }
786
787
788 if (fPathInfo) {
789 fPathInfo->updateContourData();
790 }
791
792
793 TextAnimator::ResolvedProps seed_props;
794 seed_props.fill_color = fText->fFillColor;
795 seed_props.stroke_color = fText->fStrokeColor;
796 seed_props.stroke_width = fText->fStrokeWidth;
797
799 buf.resize(fFragments.size(), { seed_props, 0 });
800
801
802 for (const auto& animator : fAnimators) {
803 animator->modulateProps(fMaps, buf);
804 }
805
807 switch (fAnchorPointGrouping) {
808
809 case AnchorPointGrouping::kWord: grouping_domain = &fMaps.
fWordsMap;
break;
810 case AnchorPointGrouping::kLine: grouping_domain = &fMaps.
fLinesMap;
break;
811
812 default: break;
813 }
814
815 size_t grouping_span_index = 0;
816 SkV2 current_line_offset = { 0, 0 };
817
819 const TextAnimator::DomainSpan& line_span) {
820 SkV2 total_spacing = {0,0};
821 float total_tracking = 0;
822
823
824 if (fRequiresLineAdjustments && line_span.fCount) {
825 for (size_t i = line_span.fOffset; i < line_span.fOffset + line_span.fCount; ++i) {
826 const auto& props = buf[i].props;
827 total_spacing += props.line_spacing;
828 total_tracking += props.tracking;
829 }
830
831
832
833 total_tracking -= 0.5f * (buf[line_span.fOffset].props.tracking +
834 buf[line_span.fOffset + line_span.fCount - 1].props.tracking);
835 }
836
837 return std::make_tuple(total_spacing, total_tracking);
838 };
839
840
841 for (const auto& line_span : fMaps.fLinesMap) {
842 const auto [line_spacing, line_tracking] = compute_linewide_props(buf, line_span);
843 const auto align_offset = -line_tracking * align_factor(fText->fHAlign);
844
845
846 if (&line_span != &fMaps.
fLinesMap.front() && line_span.fCount) {
847
848
849 current_line_offset += line_spacing / line_span.fCount;
850 }
851
852 float tracking_acc = 0;
853 for (size_t i = line_span.fOffset; i < line_span.fOffset + line_span.fCount; ++i) {
854
855 if (grouping_domain && i >= (*grouping_domain)[grouping_span_index].fOffset +
856 (*grouping_domain)[grouping_span_index].fCount) {
857 grouping_span_index += 1;
858 SkASSERT(i < (*grouping_domain)[grouping_span_index].fOffset +
859 (*grouping_domain)[grouping_span_index].fCount);
860 }
861
862 const auto& props = buf[i].props;
863 const auto& frag = fFragments[i];
864
865
866
867
868
869
870
871
872 const auto track_before = i > line_span.fOffset
873 ? props.tracking * 0.5f : 0.0f,
874 track_after = i < line_span.fOffset + line_span.fCount - 1
875 ? props.tracking * 0.5f : 0.0f;
876
877 const auto frag_offset = current_line_offset +
878 SkV2{align_offset + tracking_acc + track_before, 0};
879
880 tracking_acc += track_before + track_after;
881
882 this->pushPropsToFragment(props, frag, frag_offset, fGroupingAlignment * .01f,
883 grouping_domain ? &(*grouping_domain)[grouping_span_index]
884 : nullptr);
885 }
886 }
887}
std::vector< DomainSpan > DomainMap
std::vector< AnimatedPropsModulator > ModulatorBuffer