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