start a wrapper for color fonts
authorreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 31 May 2013 20:17:57 +0000 (20:17 +0000)
committerreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 31 May 2013 20:17:57 +0000 (20:17 +0000)
BUG=
R=bungeman@google.com

Review URL: https://codereview.chromium.org/14890016

git-svn-id: http://skia.googlecode.com/svn/trunk@9381 2bbb7eff-a529-9590-31e7-b0007b416f81

gm/colortype.cpp [new file with mode: 0644]
gyp/gmslides.gypi
gyp/utils.gyp
include/core/SkTypeface.h
src/fonts/SkGScalerContext.cpp [new file with mode: 0644]
src/fonts/SkGScalerContext.h [new file with mode: 0644]

diff --git a/gm/colortype.cpp b/gm/colortype.cpp
new file mode 100644 (file)
index 0000000..68576b8
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2013 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 "SkGradientShader.h"
+#include "../src/fonts/SkGScalerContext.h"
+
+class ColorTypeGM : public skiagm::GM {
+public:
+    ColorTypeGM() {
+        const SkColor colors[] = {
+            SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
+            SK_ColorMAGENTA, SK_ColorCYAN, SK_ColorYELLOW
+        };
+        SkShader* s = SkGradientShader::CreateSweep(0,0, colors, NULL,
+                                                    SK_ARRAY_COUNT(colors));
+        SkMatrix local;
+        local.setRotate(180);
+        s->setLocalMatrix(local);
+        
+        SkPaint paint;
+        paint.setAntiAlias(true);
+        paint.setShader(s)->unref();
+        
+        SkAutoTUnref<SkTypeface> orig(SkTypeface::CreateFromName("Times",
+                                                         SkTypeface::kBold));
+        fColorType = SkNEW_ARGS(SkGTypeface, (orig, paint));
+    }
+    
+    virtual ~ColorTypeGM() {
+        fColorType->unref();
+    }
+
+protected:
+    virtual SkString onShortName() SK_OVERRIDE {
+        return SkString("colortype");
+    }
+
+    virtual SkISize onISize() SK_OVERRIDE {
+        return SkISize::Make(640, 480);
+    }
+
+    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
+        SkPaint paint;
+        paint.setAntiAlias(true);
+        paint.setTypeface(fColorType);
+        
+        for (int size = 10; size <= 100; size += 10) {
+            paint.setTextSize(size);
+            canvas->translate(0, paint.getFontMetrics(NULL));
+            canvas->drawText("Hamburgefons", 12, 10, 10, paint);
+        }
+    }
+
+    virtual uint32_t onGetFlags() const { return kSkipPipe_Flag; }
+
+private:
+    SkTypeface* fColorType;
+
+    typedef skiagm::GM INHERITED;
+};
+
+DEF_GM( return SkNEW(ColorTypeGM); )
index e56d62b..641e9e0 100644 (file)
@@ -19,6 +19,7 @@
     '../gm/circles.cpp',
     '../gm/colorfilterimagefilter.cpp',
     '../gm/colormatrix.cpp',
+    '../gm/colortype.cpp',
     '../gm/complexclip.cpp',
     '../gm/complexclip2.cpp',
     '../gm/composeshader.cpp',
index a1820c0..0791e19 100644 (file)
         '../src/utils/win/SkHRESULT.cpp',
         '../src/utils/win/SkIStream.cpp',
         '../src/utils/win/SkWGL_win.cpp',
+        
+        #testing
+        '../src/fonts/SkGScalerContext.cpp',
+        '../src/fonts/SkGScalerContext.h',
       ],
       'sources!': [
           '../src/utils/SDL/SkOSWindow_SDL.cpp',
index c91fa42..a314e0f 100644 (file)
@@ -203,6 +203,15 @@ public:
     SkStream* openStream(int* ttcIndex) const;
     SkScalerContext* createScalerContext(const SkDescriptor*) const;
 
+    // PRIVATE / EXPERIMENTAL -- do not call
+    void filterRec(SkScalerContextRec* rec) const {
+        this->onFilterRec(rec);
+    }
+    // PRIVATE / EXPERIMENTAL -- do not call
+    void getFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
+        this->onGetFontDescriptor(desc, isLocal);
+    }
+
 protected:
     /** uniqueID must be unique and non-zero
     */
diff --git a/src/fonts/SkGScalerContext.cpp b/src/fonts/SkGScalerContext.cpp
new file mode 100644 (file)
index 0000000..4de261b
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkGScalerContext.h"
+#include "SkGlyph.h"
+#include "SkPath.h"
+#include "SkCanvas.h"
+
+class SkGScalerContext : public SkScalerContext {
+public:
+    SkGScalerContext(SkGTypeface*, const SkDescriptor*);
+    virtual ~SkGScalerContext();
+    
+protected:
+    virtual unsigned generateGlyphCount() SK_OVERRIDE;
+    virtual uint16_t generateCharToGlyph(SkUnichar) SK_OVERRIDE;
+    virtual void generateAdvance(SkGlyph*) SK_OVERRIDE;
+    virtual void generateMetrics(SkGlyph*) SK_OVERRIDE;
+    virtual void generateImage(const SkGlyph&) SK_OVERRIDE;
+    virtual void generatePath(const SkGlyph&, SkPath*) SK_OVERRIDE;
+    virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
+                                     SkPaint::FontMetrics* mY) SK_OVERRIDE;
+    
+private:
+    SkGTypeface*     fFace;
+    SkScalerContext* fProxy;
+    SkMatrix         fMatrix;
+};
+
+#define STD_SIZE    1
+
+#include "SkDescriptor.h"
+
+SkGScalerContext::SkGScalerContext(SkGTypeface* face, const SkDescriptor* desc)
+        : SkScalerContext(face, desc)
+        , fFace(face)
+{
+
+    size_t  descSize = SkDescriptor::ComputeOverhead(1) + sizeof(SkScalerContext::Rec);
+    SkAutoDescriptor ad(descSize);
+    SkDescriptor*    newDesc = ad.getDesc();
+
+    newDesc->init();
+    void* entry = newDesc->addEntry(kRec_SkDescriptorTag,
+                                    sizeof(SkScalerContext::Rec), &fRec);
+    {
+        SkScalerContext::Rec* rec = (SkScalerContext::Rec*)entry;
+        rec->fTextSize = STD_SIZE;
+        rec->fPreScaleX = SK_Scalar1;
+        rec->fPreSkewX = 0;
+        rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
+        rec->fPost2x2[1][0] = rec->fPost2x2[0][1] = 0;
+    }
+    SkASSERT(descSize == newDesc->getLength());
+    newDesc->computeChecksum();
+
+    fProxy = face->proxy()->createScalerContext(newDesc);
+
+    fRec.getSingleMatrix(&fMatrix);
+    fMatrix.preScale(SK_Scalar1 / STD_SIZE, SK_Scalar1 / STD_SIZE);
+}
+
+SkGScalerContext::~SkGScalerContext() {
+    SkDELETE(fProxy);
+}
+
+unsigned SkGScalerContext::generateGlyphCount() {
+    return fProxy->getGlyphCount();
+}
+
+uint16_t SkGScalerContext::generateCharToGlyph(SkUnichar uni) {
+    return fProxy->charToGlyphID(uni);
+}
+
+void SkGScalerContext::generateAdvance(SkGlyph* glyph) {
+    fProxy->getAdvance(glyph);
+    
+    SkVector advance;
+    fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
+                  SkFixedToScalar(glyph->fAdvanceY), &advance);
+    glyph->fAdvanceX = SkScalarToFixed(advance.fX);
+    glyph->fAdvanceY = SkScalarToFixed(advance.fY);
+}
+
+void SkGScalerContext::generateMetrics(SkGlyph* glyph) {
+    fProxy->getMetrics(glyph);
+
+    SkVector advance;
+    fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
+                  SkFixedToScalar(glyph->fAdvanceY), &advance);
+    glyph->fAdvanceX = SkScalarToFixed(advance.fX);
+    glyph->fAdvanceY = SkScalarToFixed(advance.fY);
+
+    SkPath path;
+    fProxy->getPath(*glyph, &path);
+    path.transform(fMatrix);
+
+    SkRect storage;
+    const SkPaint& paint = fFace->paint();
+    const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
+                                                        &storage,
+                                                        SkPaint::kFill_Style);
+    SkIRect ibounds;
+    newBounds.roundOut(&ibounds);
+    glyph->fLeft = ibounds.fLeft;
+    glyph->fTop = ibounds.fTop;
+    glyph->fWidth = ibounds.width();
+    glyph->fHeight = ibounds.height();
+    glyph->fMaskFormat = SkMask::kARGB32_Format;
+}
+
+void SkGScalerContext::generateImage(const SkGlyph& glyph) {
+    if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
+        SkPath path;
+        fProxy->getPath(glyph, &path);
+        
+        SkBitmap bm;
+        bm.setConfig(SkBitmap::kARGB_8888_Config, glyph.fWidth, glyph.fHeight,
+                     glyph.rowBytes());
+        bm.setPixels(glyph.fImage);
+        bm.eraseColor(0);
+        
+        SkCanvas canvas(bm);
+        canvas.translate(-glyph.fLeft, -glyph.fTop);
+        canvas.concat(fMatrix);
+        canvas.drawPath(path, fFace->paint());
+    } else {
+        fProxy->getImage(glyph);
+    }
+}
+
+void SkGScalerContext::generatePath(const SkGlyph& glyph, SkPath* path) {
+    fProxy->getPath(glyph, path);
+    path->transform(fMatrix);
+}
+
+void SkGScalerContext::generateFontMetrics(SkPaint::FontMetrics*,
+                                           SkPaint::FontMetrics* metrics) {
+    fProxy->getFontMetrics(metrics);
+    if (metrics) {
+        SkScalar scale = fMatrix.getScaleY();
+        metrics->fTop = SkScalarMul(metrics->fTop, scale);
+        metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
+        metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
+        metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
+        metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
+        metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
+        metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
+        metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
+        metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkTypefaceCache.h"
+
+SkGTypeface::SkGTypeface(SkTypeface* proxy, const SkPaint& paint)
+    : SkTypeface(proxy->style(), SkTypefaceCache::NewFontID(), false)
+    , fProxy(SkRef(proxy))
+    , fPaint(paint) {}
+
+SkGTypeface::~SkGTypeface() {
+    fProxy->unref();
+}
+
+SkScalerContext* SkGTypeface::onCreateScalerContext(
+                                            const SkDescriptor* desc) const {
+    return SkNEW_ARGS(SkGScalerContext, (const_cast<SkGTypeface*>(this), desc));
+}
+
+void SkGTypeface::onFilterRec(SkScalerContextRec* rec) const {
+    fProxy->filterRec(rec);
+}
+
+SkAdvancedTypefaceMetrics* SkGTypeface::onGetAdvancedTypefaceMetrics(
+                                SkAdvancedTypefaceMetrics::PerGlyphInfo info,
+                                const uint32_t* glyphIDs,
+                                uint32_t glyphIDsCount) const {
+    return fProxy->getAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount);
+}
+
+SkStream* SkGTypeface::onOpenStream(int* ttcIndex) const {
+    return fProxy->openStream(ttcIndex);
+}
+
+void SkGTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
+                                      bool* isLocal) const {
+    fProxy->getFontDescriptor(desc, isLocal);
+}
+
+int SkGTypeface::onGetUPEM() const {
+    return fProxy->getUnitsPerEm();
+}
+
+int SkGTypeface::onGetTableTags(SkFontTableTag tags[]) const {
+    return fProxy->getTableTags(tags);
+}
+
+size_t SkGTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
+                                    size_t length, void* data) const {
+    return fProxy->getTableData(tag, offset, length, data);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if 0
+// under construction -- defining a font purely in terms of skia primitives
+// ala an SVG-font.
+class SkGFont : public SkRefCnt {
+public:
+    virtual ~SkGFont();
+    
+    int unicharToGlyph(SkUnichar) const;
+    
+    int countGlyphs() const { return fCount; }
+    
+    float getAdvance(int index) const {
+        SkASSERT((unsigned)index < (unsigned)fCount);
+        return fGlyphs[index].fAdvance;
+    }
+    
+    const SkPath& getPath(int index) const {
+        SkASSERT((unsigned)index < (unsigned)fCount);
+        return fGlyphs[index].fPath;
+    }
+    
+private:
+    struct Glyph {
+        SkUnichar   fUni;
+        float       fAdvance;
+        SkPath      fPath;
+    };
+    int fCount;
+    Glyph* fGlyphs;
+    
+    friend class SkGFontBuilder;
+    SkGFont(int count, Glyph* array);
+};
+
+class SkGFontBuilder {
+public:
+    
+};
+#endif
diff --git a/src/fonts/SkGScalerContext.h b/src/fonts/SkGScalerContext.h
new file mode 100644 (file)
index 0000000..504bc7b
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkGScalerContext_DEFINED
+#define SkGScalerContext_DEFINED
+
+#include "SkScalerContext.h"
+#include "SkTypeface.h"
+
+class SkGTypeface : public SkTypeface {
+public:
+    SkGTypeface(SkTypeface* proxy, const SkPaint&);
+    virtual ~SkGTypeface();
+    
+    SkTypeface* proxy() const { return fProxy; }
+    const SkPaint& paint() const { return fPaint; }
+
+protected:
+    virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE;
+    virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE;
+    virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
+                                    SkAdvancedTypefaceMetrics::PerGlyphInfo,
+                                    const uint32_t* glyphIDs,
+                                    uint32_t glyphIDsCount) const SK_OVERRIDE;
+    virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE;
+    virtual void onGetFontDescriptor(SkFontDescriptor*, bool* isLocal) const SK_OVERRIDE;
+    
+    virtual int onGetUPEM() const SK_OVERRIDE;
+    
+    virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE;
+    virtual size_t onGetTableData(SkFontTableTag, size_t offset,
+                                  size_t length, void* data) const SK_OVERRIDE;
+    
+private:
+    SkTypeface* fProxy;
+    SkPaint     fPaint;
+};
+
+#endif