blob: e2fa554c9c09757c83823c1cbf0d89e2ca599989 [file] [log] [blame]
joshualitte49109f2015-07-17 12:47:39 -07001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "sk_tool_utils.h"
9#include "SkCanvas.h"
10#include "SkPaint.h"
11#include "SkPoint.h"
12#include "SkTextBlob.h"
13#include "SkFontMgr.h"
14#include "SkGraphics.h"
15#include "SkSurface.h"
16#include "SkTypeface.h"
17
18#ifdef SK_BUILD_FOR_WIN
19 #include "SkTypeface_win.h"
20#endif
21
22#include "Test.h"
23
24#if SK_SUPPORT_GPU
25#include "GrContextFactory.h"
26
27struct TextBlobWrapper {
joshualittbedf7e52015-07-23 08:09:35 -070028 // This class assumes it 'owns' the textblob it wraps, and thus does not need to take a ref
29 explicit TextBlobWrapper(const SkTextBlob* blob) : fBlob(blob) {}
joshualitte49109f2015-07-17 12:47:39 -070030 TextBlobWrapper(const TextBlobWrapper& blob) : fBlob(SkRef(blob.fBlob.get())) {}
31
32 SkAutoTUnref<const SkTextBlob> fBlob;
33};
34
35static void draw(SkCanvas* canvas, int redraw, const SkTArray<TextBlobWrapper>& blobs) {
joshualitt404d9d62015-07-22 11:00:32 -070036 int yOffset = 0;
joshualitte49109f2015-07-17 12:47:39 -070037 for (int r = 0; r < redraw; r++) {
38 for (int i = 0; i < blobs.count(); i++) {
joshualitt404d9d62015-07-22 11:00:32 -070039 const SkTextBlob* blob = blobs[i].fBlob.get();
40 const SkRect& bounds = blob->bounds();
41 yOffset += SkScalarCeilToInt(bounds.height());
joshualitte49109f2015-07-17 12:47:39 -070042 SkPaint paint;
joshualitt404d9d62015-07-22 11:00:32 -070043 canvas->drawTextBlob(blob, 0, SkIntToScalar(yOffset), paint);
joshualitte49109f2015-07-17 12:47:39 -070044 }
45 }
46}
47
48// limit this just so we don't take too long to draw
49#define MAX_TOTAL_TEXT 4096
50#define MAX_CHAR 256
51#define MAX_FAMILIES 5
52
53// This test hammers the GPU textblobcache and font atlas
joshualitt404d9d62015-07-22 11:00:32 -070054DEF_GPUTEST(TextBlobCache, reporter, factory) {
joshualitte49109f2015-07-17 12:47:39 -070055 // setup surface
56 uint32_t flags = 0;
57 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
58
joshualitt404d9d62015-07-22 11:00:32 -070059 GrContext* ctx = factory->get(GrContextFactory::kNative_GLContextType);
joshualitte49109f2015-07-17 12:47:39 -070060 SkImageInfo info = SkImageInfo::Make(1024, 768, kN32_SkColorType, kPremul_SkAlphaType);
61 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(ctx, SkSurface::kNo_Budgeted, info,
62 0, &props));
63 REPORTER_ASSERT(reporter, surface);
64 if (!surface) {
65 return;
66 }
67
68 SkCanvas* canvas = surface->getCanvas();
69
70 SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
71
72 int count = SkMin32(fm->countFamilies(), MAX_FAMILIES);
73
74 // make a ton of text
75 uint16_t text[MAX_TOTAL_TEXT];
76 for (int i = 0; i < MAX_TOTAL_TEXT; i++) {
77 text[i] = i % MAX_CHAR;
78 }
79
80 // generate textblobs
81 SkTArray<TextBlobWrapper> blobs;
82 for (int i = 0; i < count; i++) {
83 SkPaint paint;
84 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
85 paint.setTextSize(256); // draw big glyphs to really stress the atlas
86
87 SkString familyName;
88 fm->getFamilyName(i, &familyName);
89 SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i));
90 for (int j = 0; j < set->count(); ++j) {
91 SkFontStyle fs;
92 set->getStyle(j, &fs, NULL);
93
94 SkSafeUnref(paint.setTypeface(set->createTypeface(j)));
95
96 SkTextBlobBuilder builder;
97 for (int aa = 0; aa < 2; aa++) {
98 for (int subpixel = 0; subpixel < 2; subpixel++) {
99 for (int lcd = 0; lcd < 2; lcd++) {
100 paint.setAntiAlias(SkToBool(aa));
101 paint.setSubpixelText(SkToBool(subpixel));
102 paint.setLCDRenderText(SkToBool(lcd));
103 const SkTextBlobBuilder::RunBuffer& run = builder.allocRun(paint,
104 MAX_TOTAL_TEXT,
105 0, 0,
106 NULL);
107 memcpy(run.glyphs, text, MAX_TOTAL_TEXT * sizeof(uint16_t));
108 }
109 }
110 }
111 SkNEW_APPEND_TO_TARRAY(&blobs, TextBlobWrapper, (builder.build()));
112 }
113 }
114
115 // test redraw
116 draw(canvas, 2, blobs);
117
118 // test draw after free
119 ctx->freeGpuResources();
120 draw(canvas, 1, blobs);
121
122 // test draw after abandon
123 ctx->abandonContext();
124 draw(canvas, 1, blobs);
125}
126#endif