Home | History | Annotate | Download | only in gm
      1 /*
      2  * Copyright 2013 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 "gm.h"
      9 #include "SkCanvas.h"
     10 #include "SkFontMgr.h"
     11 #include "SkGraphics.h"
     12 #include "SkTypeface.h"
     13 
     14 #ifdef SK_BUILD_FOR_WIN
     15     #include "SkTypeface_win.h"
     16 #endif
     17 
     18 // limit this just so we don't take too long to draw
     19 #define MAX_FAMILIES    30
     20 
     21 static SkScalar drawString(SkCanvas* canvas, const SkString& text, SkScalar x,
     22                            SkScalar y, const SkPaint& paint) {
     23     canvas->drawText(text.c_str(), text.size(), x, y, paint);
     24     return x + paint.measureText(text.c_str(), text.size());
     25 }
     26 
     27 class FontMgrGM : public skiagm::GM {
     28 public:
     29     FontMgrGM(SkFontMgr* fontMgr = NULL) {
     30         SkGraphics::SetFontCacheLimit(16 * 1024 * 1024);
     31 
     32         fName.set("fontmgr_iter");
     33         if (fontMgr) {
     34             fName.append("_factory");
     35             fFM.reset(fontMgr);
     36         } else {
     37             fFM.reset(SkFontMgr::RefDefault());
     38         }
     39     }
     40 
     41 protected:
     42     virtual SkString onShortName() {
     43         return fName;
     44     }
     45 
     46     virtual SkISize onISize() {
     47         return SkISize::Make(640, 1024);
     48     }
     49 
     50     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
     51         SkScalar y = 20;
     52         SkPaint paint;
     53         paint.setAntiAlias(true);
     54         paint.setLCDRenderText(true);
     55         paint.setSubpixelText(true);
     56         paint.setTextSize(17);
     57 
     58         SkFontMgr* fm = fFM;
     59         int count = SkMin32(fm->countFamilies(), MAX_FAMILIES);
     60 
     61         for (int i = 0; i < count; ++i) {
     62             SkString fname;
     63             fm->getFamilyName(i, &fname);
     64             paint.setTypeface(NULL);
     65             (void)drawString(canvas, fname, 20, y, paint);
     66 
     67             SkScalar x = 220;
     68 
     69             SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i));
     70             for (int j = 0; j < set->count(); ++j) {
     71                 SkString sname;
     72                 SkFontStyle fs;
     73                 set->getStyle(j, &fs, &sname);
     74                 sname.appendf(" [%d %d %d]", fs.weight(), fs.width(), fs.isItalic());
     75 
     76                 SkSafeUnref(paint.setTypeface(set->createTypeface(j)));
     77                 x = drawString(canvas, sname, x, y, paint) + 20;
     78             }
     79             y += 24;
     80         }
     81     }
     82 
     83     virtual uint32_t onGetFlags() const SK_OVERRIDE {
     84         // fontdescriptors (and therefore serialization) don't yet understand
     85         // these new styles, so skip tests that exercise that for now.
     86 
     87         // If certain fonts are picked up (e.g. Microsoft Jhenghei 20MB for Regular, 12MB for Bold),
     88         // the resulting pdf can be ~700MB and crashes Chrome's PDF viewer.
     89 
     90         return kSkipPicture_Flag | kSkipPipe_Flag | kSkipPDF_Flag;
     91     }
     92 
     93 private:
     94     SkAutoTUnref<SkFontMgr> fFM;
     95     SkString fName;
     96     typedef GM INHERITED;
     97 };
     98 
     99 class FontMgrMatchGM : public skiagm::GM {
    100     SkAutoTUnref<SkFontMgr> fFM;
    101 
    102 public:
    103     FontMgrMatchGM() : fFM(SkFontMgr::RefDefault()) {
    104         SkGraphics::SetFontCacheLimit(16 * 1024 * 1024);
    105     }
    106 
    107 protected:
    108     virtual SkString onShortName() {
    109         return SkString("fontmgr_match");
    110     }
    111 
    112     virtual SkISize onISize() {
    113         return SkISize::Make(640, 1024);
    114     }
    115 
    116     void iterateFamily(SkCanvas* canvas, const SkPaint& paint,
    117                        SkFontStyleSet* fset) {
    118         SkPaint p(paint);
    119         SkScalar y = 0;
    120 
    121         for (int j = 0; j < fset->count(); ++j) {
    122             SkString sname;
    123             SkFontStyle fs;
    124             fset->getStyle(j, &fs, &sname);
    125 
    126             sname.appendf(" [%d %d]", fs.weight(), fs.width());
    127 
    128             SkSafeUnref(p.setTypeface(fset->createTypeface(j)));
    129             (void)drawString(canvas, sname, 0, y, p);
    130             y += 24;
    131         }
    132     }
    133 
    134     void exploreFamily(SkCanvas* canvas, const SkPaint& paint,
    135                        SkFontStyleSet* fset) {
    136         SkPaint p(paint);
    137         SkScalar y = 0;
    138 
    139         for (int weight = 100; weight <= 900; weight += 200) {
    140             for (int width = 1; width <= 9; width += 2) {
    141                 SkFontStyle fs(weight, width, SkFontStyle::kUpright_Slant);
    142                 SkTypeface* face = fset->matchStyle(fs);
    143                 if (face) {
    144                     SkString str;
    145                     str.printf("request [%d %d]", fs.weight(), fs.width());
    146                     p.setTypeface(face)->unref();
    147                     (void)drawString(canvas, str, 0, y, p);
    148                     y += 24;
    149                 }
    150             }
    151         }
    152     }
    153 
    154     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
    155         SkPaint paint;
    156         paint.setAntiAlias(true);
    157         paint.setLCDRenderText(true);
    158         paint.setSubpixelText(true);
    159         paint.setTextSize(17);
    160 
    161         static const char* gNames[] = {
    162             "Helvetica Neue", "Arial"
    163         };
    164 
    165         SkAutoTUnref<SkFontStyleSet> fset;
    166         for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); ++i) {
    167             fset.reset(fFM->matchFamily(gNames[i]));
    168             if (fset->count() > 0) {
    169                 break;
    170             }
    171         }
    172         if (NULL == fset.get()) {
    173             return;
    174         }
    175 
    176         canvas->translate(20, 40);
    177         this->exploreFamily(canvas, paint, fset);
    178         canvas->translate(150, 0);
    179         this->iterateFamily(canvas, paint, fset);
    180     }
    181 
    182     virtual uint32_t onGetFlags() const SK_OVERRIDE {
    183         // fontdescriptors (and therefore serialization) don't yet understand
    184         // these new styles, so skip tests that exercise that for now.
    185         return kSkipPicture_Flag | kSkipPipe_Flag;
    186     }
    187 
    188 private:
    189     typedef GM INHERITED;
    190 };
    191 
    192 //////////////////////////////////////////////////////////////////////////////
    193 
    194 DEF_GM( return SkNEW(FontMgrGM); )
    195 DEF_GM( return SkNEW(FontMgrMatchGM); )
    196 
    197 #ifdef SK_BUILD_FOR_WIN
    198     DEF_GM( return SkNEW_ARGS(FontMgrGM, (SkFontMgr_New_DirectWrite())); )
    199 #endif
    200