@@ -843,183 +843,80 @@ size_t SkTextBlob::serialize(const SkSerialProcs& procs, void* memory, size_t me
843843// /////////////////////////////////////////////////////////////////////////////////////////////////
844844
845845namespace {
846-
847- class TextInterceptsIter {
848- public:
849- TextInterceptsIter (const SkGlyphID glyphs[], int count, const SkFont& font,
850- const SkPaint* paint, const SkScalar bounds[2 ], SkScalar x, SkScalar y);
851-
852- /* *
853- * Returns false when all of the text has been consumed
854- */
855- bool next (SkScalar* array, int * count);
856-
857- void setPosition (SkScalar x, SkScalar y) {
858- SkScalar xOffset = 0 ;
859- for (int i = 0 ; i < (int ) SK_ARRAY_COUNT (fBounds ); ++i) {
860- SkScalar bound = fBoundsBase [i] - y;
861- fBounds [i] = bound / fScale ;
862- }
863-
864- fXPos = xOffset + x;
865- fPrevAdvance = 0 ;
866- }
867-
868- private:
869- SkExclusiveStrikePtr fCache ;
870- SkFont fFont ;
871- SkPaint fPaint ;
872- SkScalar fScale ;
873- SkScalar fPrevAdvance ;
874- const SkGlyphID* fGlyphs ;
875- const SkGlyphID* fStop ;
876-
877- SkScalar fXPos ; // accumulated xpos, returned in next
878-
879- SkScalar fBounds [2 ];
880- SkScalar fBoundsBase [2 ];
881- };
882-
883- TextInterceptsIter::TextInterceptsIter (const SkGlyphID glyphs[],
884- int count,
885- const SkFont& font,
886- const SkPaint* paint,
887- const SkScalar bounds[2 ],
888- SkScalar x, SkScalar y)
889- : fFont (font) {
890- SkAssertResult (count >= 0 );
891-
892- if (paint) {
893- fPaint = *paint;
894- }
895- fPaint .setMaskFilter (nullptr ); // don't want this affecting our path-cache lookup
896-
897- // can't use our canonical size if we need to apply patheffects
898- if (fPaint .getPathEffect () == nullptr ) {
846+ int get_glyph_run_intercepts (const SkGlyphRun& glyphRun,
847+ const SkPaint& paint,
848+ const SkScalar bounds[2 ],
849+ SkScalar intervals[],
850+ int * intervalCount) {
851+ SkScalar scale = SK_Scalar1;
852+ SkPaint interceptPaint{paint};
853+ SkFont interceptFont{glyphRun.font ()};
854+
855+ interceptPaint.setMaskFilter (nullptr ); // don't want this affecting our path-cache lookup
856+
857+ // can't use our canonical size if we need to apply path effects
858+ if (interceptPaint.getPathEffect () == nullptr ) {
899859 // If the wrong size is going to be used, don't hint anything.
900- fFont .setHinting (SkFontHinting::kNone );
901- fFont .setSubpixel (true );
902- fScale = fFont .getSize () / SkFontPriv::kCanonicalTextSizeForPaths ;
903- fFont .setSize (SkIntToScalar (SkFontPriv::kCanonicalTextSizeForPaths ));
860+ interceptFont .setHinting (SkFontHinting::kNone );
861+ interceptFont .setSubpixel (true );
862+ scale = interceptFont .getSize () / SkFontPriv::kCanonicalTextSizeForPaths ;
863+ interceptFont .setSize (SkIntToScalar (SkFontPriv::kCanonicalTextSizeForPaths ));
904864 // Note: fScale can be zero here (even if it wasn't before the divide). It can also
905865 // be very very small. We call sk_ieee_float_divide below to ensure IEEE divide behavior,
906866 // since downstream we will check for the resulting coordinates being non-finite anyway.
907867 // Thus we don't need to check for zero here.
908- if (fPaint .getStrokeWidth () > 0 && fPaint .getStyle () != SkPaint::kFill_Style ) {
909- fPaint .setStrokeWidth (sk_ieee_float_divide (fPaint .getStrokeWidth (), fScale ));
868+ if (interceptPaint.getStrokeWidth () > 0
869+ && interceptPaint.getStyle () != SkPaint::kFill_Style ) {
870+ interceptPaint.setStrokeWidth (
871+ sk_ieee_float_divide (interceptPaint.getStrokeWidth (), scale));
910872 }
911- } else {
912- fScale = SK_Scalar1;
913873 }
914874
915- SkPaint::Style prevStyle = fPaint .getStyle ();
916- auto prevPE = fPaint .refPathEffect ();
917- auto prevMF = fPaint .refMaskFilter ();
918- fPaint .setStyle (SkPaint::kFill_Style );
919- fPaint .setPathEffect (nullptr );
875+ interceptPaint.setStyle (SkPaint::kFill_Style );
876+ interceptPaint.setPathEffect (nullptr );
920877
921- SkStrikeSpec strikeSpec = SkStrikeSpec::MakeWithNoDevice (fFont , &fPaint );
922- fCache = strikeSpec.findOrCreateExclusiveStrike ();
923-
924- fPaint .setStyle (prevStyle);
925- fPaint .setPathEffect (std::move (prevPE));
926- fPaint .setMaskFilter (std::move (prevMF));
927-
928- // now compute fXOffset if needed
878+ SkStrikeSpec strikeSpec = SkStrikeSpec::MakeWithNoDevice (interceptFont, &interceptPaint);
879+ auto cache = strikeSpec.findOrCreateExclusiveStrike ();
929880
930881 SkScalar xOffset = 0 ;
931- fXPos = xOffset;
932- fPrevAdvance = 0 ;
882+ SkScalar xPos = xOffset;
883+ SkScalar prevAdvance = 0 ;
933884
934- fGlyphs = glyphs;
935- fStop = glyphs + count ;
885+ // The typeface is scaled, so un-scale the bounds to be in the space of the typeface.
886+ SkScalar scaledBounds[ 2 ] = {bounds[ 0 ] / scale, bounds[ 1 ] / scale} ;
936887
937- fBoundsBase [0 ] = bounds[0 ];
938- fBoundsBase [1 ] = bounds[1 ];
939- this ->setPosition (x, y);
940- }
888+ const SkPoint* posCursor = glyphRun.positions ().begin ();
889+ for (auto glyphID : glyphRun.glyphsIDs ()) {
890+ SkPoint pos = *posCursor++;
941891
942- bool TextInterceptsIter::next (SkScalar* array, int * count) {
943- SkASSERT (fGlyphs < fStop );
944- SkGlyph* glyph = fCache ->glyph (*fGlyphs ++);
945- fXPos += fPrevAdvance * fScale ;
946- fPrevAdvance = glyph->advanceX ();
947- if (fCache ->preparePath (glyph) != nullptr ) {
948- fCache ->findIntercepts (fBounds , fScale , fXPos , glyph, array, count);
949- }
950- return fGlyphs < fStop ;
951- }
952-
953- enum class TextType {
954- kText ,
955- kPosText
956- };
957-
958- template <TextType TextType, typename Func>
959- static int get_text_intercepts (
960- const SkFont& font, const SkPaint* paint, const SkGlyphID* glyphs,
961- int glyphCount, const SkScalar* bounds, SkScalar* array, Func posMaker) {
962- SkASSERT (glyphCount == 0 || glyphs != nullptr );
963-
964- const SkPoint pos0 = posMaker (0 );
965- TextInterceptsIter iter (glyphs, glyphCount, font, paint, bounds, pos0.x (), pos0.y ());
966-
967- int i = 0 ;
968- int count = 0 ;
969- while (iter.next (array, &count)) {
970- if (TextType == TextType::kPosText ) {
971- const SkPoint pos = posMaker (++i);
972- iter.setPosition (pos.x (), pos.y ());
892+ SkGlyph* glyph = cache->glyph (glyphID);
893+ xPos += prevAdvance * scale;
894+ prevAdvance = glyph->advanceX ();
895+ if (cache->preparePath (glyph) != nullptr ) {
896+ cache->findIntercepts (scaledBounds, scale, pos.x (), glyph, intervals, intervalCount);
973897 }
974898 }
975-
976- return count;
899+ return *intervalCount;
977900}
978-
979901} // namespace
980902
981903int SkTextBlob::getIntercepts (const SkScalar bounds[2 ], SkScalar intervals[],
982904 const SkPaint* paint) const {
983- int count = 0 ;
984- SkTextBlobRunIterator it (this );
985905
986- while (!it.done ()) {
987- SkScalar* runIntervals = intervals ? intervals + count : nullptr ;
988- const SkFont& font = it.font ();
989- const SkGlyphID* glyphs = it.glyphs ();
990- const int glyphCount = it.glyphCount ();
991-
992- switch (it.positioning ()) {
993- case SkTextBlobRunIterator::kDefault_Positioning : {
994- SkPoint loc = it.offset ();
995- count += get_text_intercepts<TextType::kText >(
996- font, paint, glyphs, glyphCount, bounds, runIntervals, [loc](int ) {
997- return loc;
998- });
999- } break ;
1000- case SkTextBlobRunIterator::kHorizontal_Positioning : {
1001- const SkScalar* xpos = it.pos ();
1002- const SkScalar constY = it.offset ().fY ;
1003- count += get_text_intercepts<TextType::kPosText >(
1004- font, paint, glyphs, glyphCount, bounds, runIntervals,
1005- [xpos, constY](int i) {
1006- return SkPoint::Make (xpos[i], constY);
1007- });
1008- } break ;
1009- case SkTextBlobRunIterator::kFull_Positioning : {
1010- const SkPoint* pos = reinterpret_cast <const SkPoint*>(it.pos ());
1011- count += get_text_intercepts<TextType::kPosText >(
1012- font, paint, glyphs, glyphCount, bounds, runIntervals, [pos](int i) {
1013- return pos[i];
1014- });
1015- } break ;
1016- case SkTextBlobRunIterator::kRSXform_Positioning :
1017- // Unimplemented for now -- can/should we try to make this work?
1018- break ;
1019- }
906+ SkTLazy<SkPaint> defaultPaint;
907+ if (paint == nullptr ) {
908+ defaultPaint.init ();
909+ paint = defaultPaint.get ();
910+ }
1020911
1021- it.next ();
912+ SkGlyphRunBuilder builder;
913+ builder.textBlobToGlyphRunListIgnoringRSXForm (*paint, *this , SkPoint{0 , 0 });
914+ auto glyphRunList = builder.useGlyphRunList ();
915+
916+ int intervalCount = 0 ;
917+ for (const SkGlyphRun& glyphRun : glyphRunList) {
918+ intervalCount = get_glyph_run_intercepts (glyphRun, *paint, bounds, intervals, &intervalCount);
1022919 }
1023920
1024- return count ;
921+ return intervalCount ;
1025922}
0 commit comments