diff options
Diffstat (limited to 'chromium/third_party/skia/gm/typeface.cpp')
-rw-r--r-- | chromium/third_party/skia/gm/typeface.cpp | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/chromium/third_party/skia/gm/typeface.cpp b/chromium/third_party/skia/gm/typeface.cpp new file mode 100644 index 00000000000..f2c56a591ed --- /dev/null +++ b/chromium/third_party/skia/gm/typeface.cpp @@ -0,0 +1,221 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gm.h" +#include "SkCanvas.h" +#include "SkString.h" +#include "SkTypeface.h" +#include "SkTypes.h" + +static const char* gFaces[] = { + "Times Roman", + "Hiragino Maru Gothic Pro", + "Papyrus", + "Helvetica", + "Courier New" +}; + +class TypefaceGM : public skiagm::GM { +public: + TypefaceGM() { + fFaces = new SkTypeface*[SK_ARRAY_COUNT(gFaces)]; + for (size_t i = 0; i < SK_ARRAY_COUNT(gFaces); i++) { + fFaces[i] = SkTypeface::CreateFromName(gFaces[i], SkTypeface::kNormal); + } + } + + virtual ~TypefaceGM() { + for (size_t i = 0; i < SK_ARRAY_COUNT(gFaces); i++) { + SkSafeUnref(fFaces[i]); + } + delete [] fFaces; + } + +protected: + virtual SkString onShortName() SK_OVERRIDE { + return SkString("typeface"); + } + + virtual SkISize onISize() SK_OVERRIDE { + return SkISize::Make(640, 480); + } + + virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { + SkString text("Typefaces are fun!"); + SkScalar y = 0; + + SkPaint paint; + paint.setAntiAlias(true); + for (int i = 0; i < (int)SK_ARRAY_COUNT(gFaces); i++) { + this->drawWithFace(text, i, y, paint, canvas); + } + // Now go backwards + for (int i = SK_ARRAY_COUNT(gFaces) - 1; i >= 0; i--) { + this->drawWithFace(text, i, y, paint, canvas); + } + } + +private: + void drawWithFace(const SkString& text, int i, SkScalar& y, SkPaint& paint, + SkCanvas* canvas) { + paint.setTypeface(fFaces[i]); + y += paint.getFontMetrics(NULL); + canvas->drawText(text.c_str(), text.size(), 0, y, paint); + } + + SkTypeface** fFaces; + + typedef skiagm::GM INHERITED; +}; + +/////////////////////////////////////////////////////////////////////////////// + +static void getGlyphPositions(const SkPaint& paint, const uint16_t glyphs[], + int count, SkScalar x, SkScalar y, SkPoint pos[]) { + SkASSERT(SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding()); + + SkAutoSTMalloc<128, SkScalar> widthStorage(count); + SkScalar* widths = widthStorage.get(); + paint.getTextWidths(glyphs, count * sizeof(uint16_t), widths); + + for (int i = 0; i < count; ++i) { + pos[i].set(x, y); + x += widths[i]; + } +} + +static void applyKerning(SkPoint pos[], const int32_t adjustments[], int count, + const SkPaint& paint) { + SkScalar scale = paint.getTextSize() / paint.getTypeface()->getUnitsPerEm(); + + SkScalar globalAdj = 0; + for (int i = 0; i < count - 1; ++i) { + globalAdj += adjustments[i] * scale; + pos[i + 1].fX += globalAdj; + } +} + +static void drawKernText(SkCanvas* canvas, const void* text, size_t len, + SkScalar x, SkScalar y, const SkPaint& paint) { + SkTypeface* face = paint.getTypeface(); + if (!face) { + canvas->drawText(text, len, x, y, paint); + return; + } + + SkAutoSTMalloc<128, uint16_t> glyphStorage(len); + uint16_t* glyphs = glyphStorage.get(); + int glyphCount = paint.textToGlyphs(text, len, glyphs); + if (glyphCount < 1) { + return; + } + + SkAutoSTMalloc<128, int32_t> adjustmentStorage(glyphCount - 1); + int32_t* adjustments = adjustmentStorage.get(); + if (!face->getKerningPairAdjustments(glyphs, glyphCount, adjustments)) { + canvas->drawText(text, len, x, y, paint); + return; + } + + SkPaint glyphPaint(paint); + glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + + SkAutoSTMalloc<128, SkPoint> posStorage(glyphCount); + SkPoint* pos = posStorage.get(); + getGlyphPositions(glyphPaint, glyphs, glyphCount, x, y, pos); + + applyKerning(pos, adjustments, glyphCount, glyphPaint); + canvas->drawPosText(glyphs, glyphCount * sizeof(uint16_t), pos, glyphPaint); +} + +static const struct { + const char* fName; + SkTypeface::Style fStyle; +} gFaceStyles[] = { + { "sans-serif", SkTypeface::kNormal }, + { "sans-serif", SkTypeface::kBold }, + { "sans-serif", SkTypeface::kItalic }, + { "sans-serif", SkTypeface::kBoldItalic }, + { "serif", SkTypeface::kNormal }, + { "serif", SkTypeface::kBold }, + { "serif", SkTypeface::kItalic }, + { "serif", SkTypeface::kBoldItalic }, + { "monospace", SkTypeface::kNormal }, + { "monospace", SkTypeface::kBold }, + { "monospace", SkTypeface::kItalic }, + { "monospace", SkTypeface::kBoldItalic }, +}; + +static const int gFaceStylesCount = SK_ARRAY_COUNT(gFaceStyles); + +class TypefaceStylesGM : public skiagm::GM { + SkTypeface* fFaces[gFaceStylesCount]; + bool fApplyKerning; + +public: + TypefaceStylesGM(bool applyKerning) : fApplyKerning(applyKerning) { + for (int i = 0; i < gFaceStylesCount; i++) { + fFaces[i] = SkTypeface::CreateFromName(gFaceStyles[i].fName, + gFaceStyles[i].fStyle); + } + } + + virtual ~TypefaceStylesGM() { + for (int i = 0; i < gFaceStylesCount; i++) { + SkSafeUnref(fFaces[i]); + } + } + +protected: + virtual SkString onShortName() SK_OVERRIDE { + SkString name("typefacestyles"); + if (fApplyKerning) { + name.append("_kerning"); + } + return name; + } + + virtual SkISize onISize() SK_OVERRIDE { + return SkISize::Make(640, 480); + } + + virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { + SkPaint paint; + paint.setAntiAlias(true); + paint.setTextSize(SkIntToScalar(30)); + + const char* text = fApplyKerning ? "Type AWAY" : "Hamburgefons"; + const size_t textLen = strlen(text); + + SkScalar x = SkIntToScalar(10); + SkScalar dy = paint.getFontMetrics(NULL); + SkScalar y = dy; + + if (fApplyKerning) { + paint.setSubpixelText(true); + } else { + paint.setLinearText(true); + } + for (int i = 0; i < gFaceStylesCount; i++) { + paint.setTypeface(fFaces[i]); + canvas->drawText(text, textLen, x, y, paint); + if (fApplyKerning) { + drawKernText(canvas, text, textLen, x + 240, y, paint); + } + y += dy; + } + } + +private: + typedef skiagm::GM INHERITED; +}; + +/////////////////////////////////////////////////////////////////////////////// + +DEF_GM( return new TypefaceGM; ) +DEF_GM( return new TypefaceStylesGM(false); ) +DEF_GM( return new TypefaceStylesGM(true); ) |