OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 #include "GrAtlasTextContext.h" | 7 #include "GrAtlasTextContext.h" |
8 | 8 |
9 #include "GrBlurUtils.h" | |
10 #include "GrDrawContext.h" | 9 #include "GrDrawContext.h" |
11 #include "GrDrawTarget.h" | 10 #include "GrDrawTarget.h" |
12 #include "GrFontScaler.h" | 11 #include "GrFontScaler.h" |
13 #include "GrStrokeInfo.h" | 12 #include "GrStrokeInfo.h" |
14 #include "GrTextBlobCache.h" | 13 #include "GrTextBlobCache.h" |
15 #include "GrTexturePriv.h" | 14 #include "GrTexturePriv.h" |
16 #include "GrVertexBuffer.h" | 15 #include "GrVertexBuffer.h" |
17 | 16 |
18 #include "SkAutoKern.h" | 17 #include "SkAutoKern.h" |
19 #include "SkColorPriv.h" | 18 #include "SkColorPriv.h" |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 if (canCache) { | 196 if (canCache) { |
198 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s
kPaint, | 197 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s
kPaint, |
199 GrAtlasTextBlob::kGra
yTextVASize))); | 198 GrAtlasTextBlob::kGra
yTextVASize))); |
200 } else { | 199 } else { |
201 cacheBlob.reset(fCache->createBlob(blob, GrAtlasTextBlob::kGrayTextV
ASize)); | 200 cacheBlob.reset(fCache->createBlob(blob, GrAtlasTextBlob::kGrayTextV
ASize)); |
202 } | 201 } |
203 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMat
rix, | 202 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMat
rix, |
204 blob, x, y, drawFilter, clip); | 203 blob, x, y, drawFilter, clip); |
205 } | 204 } |
206 | 205 |
207 this->flush(blob, cacheBlob, dc, skPaint, grPaint, drawFilter, | 206 cacheBlob->flushCached(blob, fContext, dc, this, fSurfaceProps, fDistanceAdj
ustTable, skPaint, |
208 clip, viewMatrix, clipBounds, x, y, transX, transY); | 207 grPaint, drawFilter, clip, viewMatrix, clipBounds, x,
y, transX, transY); |
209 } | 208 } |
210 | 209 |
211 inline bool GrAtlasTextContext::canDrawAsDistanceFields(const SkPaint& skPaint, | 210 inline bool GrAtlasTextContext::canDrawAsDistanceFields(const SkPaint& skPaint, |
212 const SkMatrix& viewMatr
ix) { | 211 const SkMatrix& viewMatr
ix) { |
213 // TODO: support perspective (need getMaxScale replacement) | 212 // TODO: support perspective (need getMaxScale replacement) |
214 if (viewMatrix.hasPerspective()) { | 213 if (viewMatrix.hasPerspective()) { |
215 return false; | 214 return false; |
216 } | 215 } |
217 | 216 |
218 SkScalar maxScale = viewMatrix.getMaxScale(); | 217 SkScalar maxScale = viewMatrix.getMaxScale(); |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 | 528 |
530 void GrAtlasTextContext::onDrawText(GrDrawContext* dc, | 529 void GrAtlasTextContext::onDrawText(GrDrawContext* dc, |
531 const GrClip& clip, | 530 const GrClip& clip, |
532 const GrPaint& paint, const SkPaint& skPaint
, | 531 const GrPaint& paint, const SkPaint& skPaint
, |
533 const SkMatrix& viewMatrix, | 532 const SkMatrix& viewMatrix, |
534 const char text[], size_t byteLength, | 533 const char text[], size_t byteLength, |
535 SkScalar x, SkScalar y, const SkIRect& regio
nClipBounds) { | 534 SkScalar x, SkScalar y, const SkIRect& regio
nClipBounds) { |
536 SkAutoTUnref<GrAtlasTextBlob> blob( | 535 SkAutoTUnref<GrAtlasTextBlob> blob( |
537 this->createDrawTextBlob(clip, paint, skPaint, viewMatrix, | 536 this->createDrawTextBlob(clip, paint, skPaint, viewMatrix, |
538 text, byteLength, x, y, regionClipBounds)); | 537 text, byteLength, x, y, regionClipBounds)); |
539 this->flush(blob, dc, skPaint, paint, clip, regionClipBounds); | 538 blob->flushThrowaway(fContext, dc, fSurfaceProps, fDistanceAdjustTable, skPa
int, paint, |
| 539 clip, regionClipBounds); |
540 } | 540 } |
541 | 541 |
542 void GrAtlasTextContext::onDrawPosText(GrDrawContext* dc, | 542 void GrAtlasTextContext::onDrawPosText(GrDrawContext* dc, |
543 const GrClip& clip, | 543 const GrClip& clip, |
544 const GrPaint& paint, const SkPaint& skPa
int, | 544 const GrPaint& paint, const SkPaint& skPa
int, |
545 const SkMatrix& viewMatrix, | 545 const SkMatrix& viewMatrix, |
546 const char text[], size_t byteLength, | 546 const char text[], size_t byteLength, |
547 const SkScalar pos[], int scalarsPerPosit
ion, | 547 const SkScalar pos[], int scalarsPerPosit
ion, |
548 const SkPoint& offset, const SkIRect& reg
ionClipBounds) { | 548 const SkPoint& offset, const SkIRect& reg
ionClipBounds) { |
549 SkAutoTUnref<GrAtlasTextBlob> blob( | 549 SkAutoTUnref<GrAtlasTextBlob> blob( |
550 this->createDrawPosTextBlob(clip, paint, skPaint, viewMatrix, | 550 this->createDrawPosTextBlob(clip, paint, skPaint, viewMatrix, |
551 text, byteLength, | 551 text, byteLength, |
552 pos, scalarsPerPosition, | 552 pos, scalarsPerPosition, |
553 offset, regionClipBounds)); | 553 offset, regionClipBounds)); |
554 | 554 |
555 this->flush(blob, dc, skPaint, paint, clip, regionClipBounds); | 555 blob->flushThrowaway(fContext, dc, fSurfaceProps, fDistanceAdjustTable, skPa
int, paint, clip, |
| 556 regionClipBounds); |
556 } | 557 } |
557 | 558 |
558 void GrAtlasTextContext::internalDrawBMPText(GrAtlasTextBlob* blob, int runIndex
, | 559 void GrAtlasTextContext::internalDrawBMPText(GrAtlasTextBlob* blob, int runIndex
, |
559 SkGlyphCache* cache, const SkPaint&
skPaint, | 560 SkGlyphCache* cache, const SkPaint&
skPaint, |
560 GrColor color, | 561 GrColor color, |
561 const SkMatrix& viewMatrix, | 562 const SkMatrix& viewMatrix, |
562 const char text[], size_t byteLengt
h, | 563 const char text[], size_t byteLengt
h, |
563 SkScalar x, SkScalar y) { | 564 SkScalar x, SkScalar y) { |
564 SkASSERT(byteLength == 0 || text != nullptr); | 565 SkASSERT(byteLength == 0 || text != nullptr); |
565 | 566 |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
851 height *= scale; | 852 height *= scale; |
852 sx += dx; | 853 sx += dx; |
853 sy += dy; | 854 sy += dy; |
854 SkRect glyphRect = SkRect::MakeXYWH(sx, sy, width, height); | 855 SkRect glyphRect = SkRect::MakeXYWH(sx, sy, width, height); |
855 | 856 |
856 blob->appendGlyph(runIndex, glyphRect, color, fCurrStrike, glyph, scaler, sk
Glyph, | 857 blob->appendGlyph(runIndex, glyphRect, color, fCurrStrike, glyph, scaler, sk
Glyph, |
857 sx - dx, sy - dy, scale, true); | 858 sx - dx, sy - dy, scale, true); |
858 return true; | 859 return true; |
859 } | 860 } |
860 | 861 |
861 void GrAtlasTextContext::flushRunAsPaths(GrDrawContext* dc, | |
862 const SkTextBlobRunIterator& it, | |
863 const GrClip& clip, const SkPaint& skPa
int, | |
864 SkDrawFilter* drawFilter, const SkMatri
x& viewMatrix, | |
865 const SkIRect& clipBounds, SkScalar x,
SkScalar y) { | |
866 SkPaint runPaint = skPaint; | |
867 | |
868 size_t textLen = it.glyphCount() * sizeof(uint16_t); | |
869 const SkPoint& offset = it.offset(); | |
870 | |
871 it.applyFontToPaint(&runPaint); | |
872 | |
873 if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Type))
{ | |
874 return; | |
875 } | |
876 | |
877 runPaint.setFlags(FilterTextFlags(fSurfaceProps, runPaint)); | |
878 | |
879 switch (it.positioning()) { | |
880 case SkTextBlob::kDefault_Positioning: | |
881 this->drawTextAsPath(dc, clip, runPaint, viewMatrix, | |
882 (const char *)it.glyphs(), | |
883 textLen, x + offset.x(), y + offset.y(), clipBo
unds); | |
884 break; | |
885 case SkTextBlob::kHorizontal_Positioning: | |
886 this->drawPosTextAsPath(dc, clip, runPaint, viewMatrix, | |
887 (const char*)it.glyphs(), | |
888 textLen, it.pos(), 1, SkPoint::Make(x, y + o
ffset.y()), | |
889 clipBounds); | |
890 break; | |
891 case SkTextBlob::kFull_Positioning: | |
892 this->drawPosTextAsPath(dc, clip, runPaint, viewMatrix, | |
893 (const char*)it.glyphs(), | |
894 textLen, it.pos(), 2, SkPoint::Make(x, y), c
lipBounds); | |
895 break; | |
896 } | |
897 } | |
898 | |
899 inline GrDrawBatch* | |
900 GrAtlasTextContext::createBatch(GrAtlasTextBlob* cacheBlob, const PerSubRunInfo&
info, | |
901 int glyphCount, int run, int subRun, | |
902 GrColor color, SkScalar transX, SkScalar transY, | |
903 const SkPaint& skPaint) { | |
904 GrMaskFormat format = info.maskFormat(); | |
905 GrColor subRunColor; | |
906 if (kARGB_GrMaskFormat == format) { | |
907 uint8_t paintAlpha = skPaint.getAlpha(); | |
908 subRunColor = SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAl
pha); | |
909 } else { | |
910 subRunColor = color; | |
911 } | |
912 | |
913 GrAtlasTextBatch* batch; | |
914 if (info.drawAsDistanceFields()) { | |
915 SkColor filteredColor; | |
916 SkColorFilter* colorFilter = skPaint.getColorFilter(); | |
917 if (colorFilter) { | |
918 filteredColor = colorFilter->filterColor(skPaint.getColor()); | |
919 } else { | |
920 filteredColor = skPaint.getColor(); | |
921 } | |
922 bool useBGR = SkPixelGeometryIsBGR(fSurfaceProps.pixelGeometry()); | |
923 batch = GrAtlasTextBatch::CreateDistanceField(glyphCount, fContext->getB
atchFontCache(), | |
924 fDistanceAdjustTable, filt
eredColor, | |
925 info.hasUseLCDText(), useB
GR); | |
926 } else { | |
927 batch = GrAtlasTextBatch::CreateBitmap(format, glyphCount, fContext->get
BatchFontCache()); | |
928 } | |
929 GrAtlasTextBatch::Geometry& geometry = batch->geometry(); | |
930 geometry.fBlob = SkRef(cacheBlob); | |
931 geometry.fRun = run; | |
932 geometry.fSubRun = subRun; | |
933 geometry.fColor = subRunColor; | |
934 geometry.fTransX = transX; | |
935 geometry.fTransY = transY; | |
936 batch->init(); | |
937 | |
938 return batch; | |
939 } | |
940 | |
941 inline void GrAtlasTextContext::flushRun(GrDrawContext* dc, GrPipelineBuilder* p
ipelineBuilder, | |
942 GrAtlasTextBlob* cacheBlob, int run, Gr
Color color, | |
943 SkScalar transX, SkScalar transY, | |
944 const SkPaint& skPaint) { | |
945 for (int subRun = 0; subRun < cacheBlob->fRuns[run].fSubRunInfo.count(); sub
Run++) { | |
946 const PerSubRunInfo& info = cacheBlob->fRuns[run].fSubRunInfo[subRun]; | |
947 int glyphCount = info.glyphCount(); | |
948 if (0 == glyphCount) { | |
949 continue; | |
950 } | |
951 | |
952 SkAutoTUnref<GrDrawBatch> batch(this->createBatch(cacheBlob, info, glyph
Count, run, | |
953 subRun, color, transX,
transY, | |
954 skPaint)); | |
955 dc->drawBatch(pipelineBuilder, batch); | |
956 } | |
957 } | |
958 | |
959 inline void GrAtlasTextContext::flushBigGlyphs(GrAtlasTextBlob* cacheBlob, | |
960 GrDrawContext* dc, | |
961 const GrClip& clip, const SkPaint
& skPaint, | |
962 SkScalar transX, SkScalar transY, | |
963 const SkIRect& clipBounds) { | |
964 if (!cacheBlob->fBigGlyphs.count()) { | |
965 return; | |
966 } | |
967 | |
968 for (int i = 0; i < cacheBlob->fBigGlyphs.count(); i++) { | |
969 GrAtlasTextBlob::BigGlyph& bigGlyph = cacheBlob->fBigGlyphs[i]; | |
970 bigGlyph.fVx += transX; | |
971 bigGlyph.fVy += transY; | |
972 SkMatrix ctm; | |
973 ctm.setScale(bigGlyph.fScale, bigGlyph.fScale); | |
974 ctm.postTranslate(bigGlyph.fVx, bigGlyph.fVy); | |
975 if (bigGlyph.fApplyVM) { | |
976 ctm.postConcat(cacheBlob->fViewMatrix); | |
977 } | |
978 | |
979 GrBlurUtils::drawPathWithMaskFilter(fContext, dc, clip, bigGlyph.fPath, | |
980 skPaint, ctm, nullptr, clipBounds, f
alse); | |
981 } | |
982 } | |
983 | |
984 void GrAtlasTextContext::flush(const SkTextBlob* blob, | |
985 GrAtlasTextBlob* cacheBlob, | |
986 GrDrawContext* dc, | |
987 const SkPaint& skPaint, | |
988 const GrPaint& grPaint, | |
989 SkDrawFilter* drawFilter, | |
990 const GrClip& clip, | |
991 const SkMatrix& viewMatrix, | |
992 const SkIRect& clipBounds, | |
993 SkScalar x, SkScalar y, | |
994 SkScalar transX, SkScalar transY) { | |
995 // We loop through the runs of the blob, flushing each. If any run is too l
arge, then we flush | |
996 // it as paths | |
997 GrPipelineBuilder pipelineBuilder(grPaint, dc->accessRenderTarget(), clip); | |
998 | |
999 GrColor color = grPaint.getColor(); | |
1000 | |
1001 SkTextBlobRunIterator it(blob); | |
1002 for (int run = 0; !it.done(); it.next(), run++) { | |
1003 if (cacheBlob->fRuns[run].fDrawAsPaths) { | |
1004 this->flushRunAsPaths(dc, it, clip, skPaint, | |
1005 drawFilter, viewMatrix, clipBounds, x, y); | |
1006 continue; | |
1007 } | |
1008 cacheBlob->fRuns[run].fVertexBounds.offset(transX, transY); | |
1009 this->flushRun(dc, &pipelineBuilder, cacheBlob, run, color, | |
1010 transX, transY, skPaint); | |
1011 } | |
1012 | |
1013 // Now flush big glyphs | |
1014 this->flushBigGlyphs(cacheBlob, dc, clip, skPaint, transX, transY, clipBound
s); | |
1015 } | |
1016 | |
1017 void GrAtlasTextContext::flush(GrAtlasTextBlob* cacheBlob, | |
1018 GrDrawContext* dc, | |
1019 const SkPaint& skPaint, | |
1020 const GrPaint& grPaint, | |
1021 const GrClip& clip, | |
1022 const SkIRect& clipBounds) { | |
1023 GrPipelineBuilder pipelineBuilder(grPaint, dc->accessRenderTarget(), clip); | |
1024 | |
1025 GrColor color = grPaint.getColor(); | |
1026 for (int run = 0; run < cacheBlob->fRunCount; run++) { | |
1027 this->flushRun(dc, &pipelineBuilder, cacheBlob, run, color, 0, 0, skPain
t); | |
1028 } | |
1029 | |
1030 // Now flush big glyphs | |
1031 this->flushBigGlyphs(cacheBlob, dc, clip, skPaint, 0, 0, clipBounds); | |
1032 } | |
1033 | |
1034 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 862 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
1035 | 863 |
1036 #ifdef GR_TEST_UTILS | 864 #ifdef GR_TEST_UTILS |
1037 | 865 |
1038 DRAW_BATCH_TEST_DEFINE(TextBlobBatch) { | 866 DRAW_BATCH_TEST_DEFINE(TextBlobBatch) { |
1039 static uint32_t gContextID = SK_InvalidGenID; | 867 static uint32_t gContextID = SK_InvalidGenID; |
1040 static GrAtlasTextContext* gTextContext = nullptr; | 868 static GrAtlasTextContext* gTextContext = nullptr; |
1041 static SkSurfaceProps gSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType
); | 869 static SkSurfaceProps gSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType
); |
1042 | 870 |
1043 if (context->uniqueID() != gContextID) { | 871 if (context->uniqueID() != gContextID) { |
(...skipping 29 matching lines...) Expand all Loading... |
1073 | 901 |
1074 // right now we don't handle textblobs, nor do we handle drawPosText. Since
we only | 902 // right now we don't handle textblobs, nor do we handle drawPosText. Since
we only |
1075 // intend to test the batch with this unit test, that is okay. | 903 // intend to test the batch with this unit test, that is okay. |
1076 SkAutoTUnref<GrAtlasTextBlob> blob( | 904 SkAutoTUnref<GrAtlasTextBlob> blob( |
1077 gTextContext->createDrawTextBlob(clip, grPaint, skPaint, viewMatrix,
text, | 905 gTextContext->createDrawTextBlob(clip, grPaint, skPaint, viewMatrix,
text, |
1078 static_cast<size_t>(textLen), 0, 0,
noClip)); | 906 static_cast<size_t>(textLen), 0, 0,
noClip)); |
1079 | 907 |
1080 SkScalar transX = static_cast<SkScalar>(random->nextU()); | 908 SkScalar transX = static_cast<SkScalar>(random->nextU()); |
1081 SkScalar transY = static_cast<SkScalar>(random->nextU()); | 909 SkScalar transY = static_cast<SkScalar>(random->nextU()); |
1082 const GrAtlasTextBlob::Run::SubRunInfo& info = blob->fRuns[0].fSubRunInfo[0]
; | 910 const GrAtlasTextBlob::Run::SubRunInfo& info = blob->fRuns[0].fSubRunInfo[0]
; |
1083 return gTextContext->createBatch(blob, info, textLen, 0, 0, color, transX, t
ransY, skPaint); | 911 return blob->createBatch(info, textLen, 0, 0, color, transX, transY, skPaint
, |
| 912 gSurfaceProps, gTextContext->dfAdjustTable(), |
| 913 context->getBatchFontCache()); |
1084 } | 914 } |
1085 | 915 |
1086 #endif | 916 #endif |
OLD | NEW |