aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/fontmgr.cpp94
-rw-r--r--include/core/SkLazyPtr.h (renamed from src/core/SkLazyPtr.h)6
-rw-r--r--include/core/SkThreadPriv.h (renamed from src/core/SkThreadPriv.h)0
-rw-r--r--include/core/SkTypeface.h20
-rw-r--r--src/core/SkTypeface.cpp56
5 files changed, 168 insertions, 8 deletions
diff --git a/gm/fontmgr.cpp b/gm/fontmgr.cpp
index 79868982f4..a1e7ff2a68 100644
--- a/gm/fontmgr.cpp
+++ b/gm/fontmgr.cpp
@@ -15,6 +15,13 @@
#include "SkTypeface_win.h"
#endif
+static void scale(SkRect* rect, SkScalar scale) {
+ rect->fLeft *= scale;
+ rect->fTop *= scale;
+ rect->fRight *= scale;
+ rect->fBottom *= scale;
+}
+
// limit this just so we don't take too long to draw
#define MAX_FAMILIES 30
@@ -220,9 +227,96 @@ private:
typedef GM INHERITED;
};
+class FontMgrBoundsGM : public skiagm::GM {
+public:
+ FontMgrBoundsGM() {
+ fName.set("fontmgr_bounds");
+ fFM.reset(SkFontMgr::RefDefault());
+ }
+
+ static void show_bounds(SkCanvas* canvas, const SkPaint& paint, SkScalar x, SkScalar y,
+ SkColor boundsColor) {
+ const char str[] = "jyHO[]{}@-_&%$";
+
+ const SkTypeface* tf = paint.getTypeface();
+ for (int i = 0; str[i]; ++i) {
+ canvas->drawText(&str[i], 1, x, y, paint);
+ }
+
+ SkRect r = tf->getBounds();
+ scale(&r, paint.getTextSize());
+ r.offset(x, y);
+ SkPaint p(paint);
+ p.setColor(boundsColor);
+ canvas->drawRect(r, p);
+ }
+
+protected:
+ virtual SkString onShortName() {
+ return fName;
+ }
+
+ virtual SkISize onISize() {
+ return SkISize::Make(1024, 850);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setSubpixelText(true);
+ paint.setTextSize(100);
+ paint.setStyle(SkPaint::kStroke_Style);
+
+ const SkColor boundsColors[2] = { SK_ColorRED, SK_ColorBLUE };
+
+ SkFontMgr* fm = fFM;
+ int count = SkMin32(fm->countFamilies(), 32);
+
+ int index = 0;
+ SkScalar x = 0, y = 0;
+
+ canvas->translate(80, 120);
+
+ for (int i = 0; i < count; ++i) {
+ SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i));
+ for (int j = 0; j < set->count(); ++j) {
+ SkSafeUnref(paint.setTypeface(set->createTypeface(j)));
+ if (paint.getTypeface()) {
+ show_bounds(canvas, paint, x, y, boundsColors[index & 1]);
+ index += 1;
+ x += 160;
+ if (0 == (index % 6)) {
+ x = 0;
+ y += 160;
+ }
+ if (index >= 30) {
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ virtual uint32_t onGetFlags() const SK_OVERRIDE {
+ // fontdescriptors (and therefore serialization) don't yet understand
+ // these new styles, so skip tests that exercise that for now.
+
+ // If certain fonts are picked up (e.g. Microsoft Jhenghei 20MB for Regular, 12MB for Bold),
+ // the resulting pdf can be ~700MB and crashes Chrome's PDF viewer.
+
+ return kSkipPicture_Flag | kSkipPipe_Flag | kSkipPDF_Flag;
+ }
+
+private:
+ SkAutoTUnref<SkFontMgr> fFM;
+ SkString fName;
+ typedef GM INHERITED;
+};
+
//////////////////////////////////////////////////////////////////////////////
DEF_GM( return SkNEW(FontMgrGM); )
+DEF_GM( return SkNEW(FontMgrBoundsGM); )
DEF_GM( return SkNEW(FontMgrMatchGM); )
#ifdef SK_BUILD_FOR_WIN
diff --git a/src/core/SkLazyPtr.h b/include/core/SkLazyPtr.h
index 7273079252..896dfbf88d 100644
--- a/src/core/SkLazyPtr.h
+++ b/include/core/SkLazyPtr.h
@@ -147,19 +147,19 @@ public:
SkLazyPtr() : fPtr(NULL) {}
~SkLazyPtr() { if (fPtr) { Destroy((T*)fPtr); } }
- T* get() {
+ T* get() const {
T* ptr = (T*)sk_consume_load(&fPtr);
return ptr ? ptr : Private::try_cas<T*, Destroy>(&fPtr, SkNEW(T));
}
template <typename Create>
- T* get(const Create& create) {
+ T* get(const Create& create) const {
T* ptr = (T*)sk_consume_load(&fPtr);
return ptr ? ptr : Private::try_cas<T*, Destroy>(&fPtr, create());
}
private:
- void* fPtr;
+ mutable void* fPtr;
};
diff --git a/src/core/SkThreadPriv.h b/include/core/SkThreadPriv.h
index c44cca5350..c44cca5350 100644
--- a/src/core/SkThreadPriv.h
+++ b/include/core/SkThreadPriv.h
diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h
index f67623674a..c3ff3641b7 100644
--- a/include/core/SkTypeface.h
+++ b/include/core/SkTypeface.h
@@ -12,6 +12,7 @@
#include "SkAdvancedTypefaceMetrics.h"
#include "SkFontStyle.h"
+#include "SkLazyPtr.h"
#include "SkWeakRefCnt.h"
class SkDescriptor;
@@ -282,6 +283,13 @@ public:
SkScalerContext* createScalerContext(const SkDescriptor*,
bool allowFailure = false) const;
+ /**
+ * Return a rectangle (scaled to 1-pt) that represents the union of the bounds of all
+ * of the glyphs, but each one positioned at (0,). This may be conservatively large, and
+ * will not take into account any hinting or other size-specific adjustments.
+ */
+ SkRect getBounds() const;
+
// PRIVATE / EXPERIMENTAL -- do not call
void filterRec(SkScalerContextRec* rec) const {
this->onFilterRec(rec);
@@ -333,6 +341,8 @@ protected:
virtual size_t onGetTableData(SkFontTableTag, size_t offset,
size_t length, void* data) const = 0;
+ virtual bool onComputeBounds(SkRect*) const;
+
private:
friend class SkGTypeface;
friend class SkPDFFont;
@@ -359,9 +369,13 @@ private:
static SkTypeface* CreateDefault(int style); // SkLazyPtr requires an int, not a Style.
static void DeleteDefault(SkTypeface*);
- SkFontID fUniqueID;
- SkFontStyle fStyle;
- bool fIsFixedPitch;
+ struct BoundsComputer;
+// friend struct BoundsComputer;
+
+ SkLazyPtr<SkRect> fLazyBounds;
+ SkFontID fUniqueID;
+ SkFontStyle fStyle;
+ bool fIsFixedPitch;
friend class SkPaint;
friend class SkGlyphCache; // GetDefaultTypeface
diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp
index 84cbdbfe66..c537d4aa2d 100644
--- a/src/core/SkTypeface.cpp
+++ b/src/core/SkTypeface.cpp
@@ -278,9 +278,61 @@ SkAdvancedTypefaceMetrics* SkTypeface::getAdvancedTypefaceMetrics(
return result;
}
-///////////////////////////////////////////////////////////////////////////////
-
bool SkTypeface::onGetKerningPairAdjustments(const uint16_t glyphs[], int count,
int32_t adjustments[]) const {
return false;
}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkDescriptor.h"
+#include "SkPaint.h"
+
+struct SkTypeface::BoundsComputer {
+ const SkTypeface& fTypeface;
+
+ BoundsComputer(const SkTypeface& tf) : fTypeface(tf) {}
+
+ SkRect* operator()() const {
+ SkRect* rect = SkNEW(SkRect);
+ if (!fTypeface.onComputeBounds(rect)) {
+ rect->setEmpty();
+ }
+ return rect;
+ }
+};
+
+SkRect SkTypeface::getBounds() const {
+ return *fLazyBounds.get(BoundsComputer(*this));
+}
+
+bool SkTypeface::onComputeBounds(SkRect* bounds) const {
+ // we use a big size to ensure lots of significant bits from the scalercontext.
+ // then we scale back down to return our final answer (at 1-pt)
+ const SkScalar textSize = 2048;
+ const SkScalar invTextSize = 1 / textSize;
+
+ SkPaint paint;
+ paint.setTypeface(const_cast<SkTypeface*>(this));
+ paint.setTextSize(textSize);
+ paint.setLinearText(true);
+
+ SkScalerContext::Rec rec;
+ SkScalerContext::MakeRec(paint, NULL, NULL, &rec);
+
+ SkAutoDescriptor ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
+ SkDescriptor* desc = ad.getDesc();
+ desc->init();
+ desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
+
+ SkAutoTDelete<SkScalerContext> ctx(this->createScalerContext(desc, true));
+ if (ctx.get()) {
+ SkPaint::FontMetrics fm;
+ ctx->getFontMetrics(&fm);
+ bounds->set(fm.fXMin * invTextSize, fm.fTop * invTextSize,
+ fm.fXMax * invTextSize, fm.fBottom * invTextSize);
+ return true;
+ }
+ return false;
+}
+