add typefacecache
speedup lcd blits
clean up some samples
git-svn-id: http://skia.googlecode.com/svn/trunk@1220 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/Makefile b/Makefile
index 8548612..d03c12f 100644
--- a/Makefile
+++ b/Makefile
@@ -102,6 +102,7 @@
# SRC_LIST += src/ports/SkImageDecoder_CG.cpp
SRC_LIST += src/utils/mac/SkCreateCGImageRef.cpp
SRC_LIST += src/utils/mac/SkEGLContext_mac.cpp
+ SRC_LIST += src/core/SkTypefaceCache.cpp
SRC_LIST += src/ports/SkFontHost_mac_coretext.cpp
# these are our registry-based factories
diff --git a/include/core/SkFontHost.h b/include/core/SkFontHost.h
index daa6e54..d0f7c65 100644
--- a/include/core/SkFontHost.h
+++ b/include/core/SkFontHost.h
@@ -24,7 +24,6 @@
class SkStream;
class SkWStream;
-typedef uint32_t SkFontID;
typedef uint32_t SkFontTableTag;
/** \class SkFontHost
diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h
index c415329..e13a21d 100644
--- a/include/core/SkTypeface.h
+++ b/include/core/SkTypeface.h
@@ -24,6 +24,8 @@
class SkAdvancedTypefaceMetrics;
class SkWStream;
+typedef uint32_t SkFontID;
+
/** \class SkTypeface
The SkTypeface class specifies the typeface and intrinsic style of a font.
@@ -65,13 +67,13 @@
/** Return a 32bit value for this typeface, unique for the underlying font
data. Will never return 0.
*/
- uint32_t uniqueID() const { return fUniqueID; }
+ SkFontID uniqueID() const { return fUniqueID; }
/** Return the uniqueID for the specified typeface. If the face is null,
resolve it to the default font and return its uniqueID. Will never
return 0.
*/
- static uint32_t UniqueID(const SkTypeface* face);
+ static SkFontID UniqueID(const SkTypeface* face);
/** Returns true if the two typefaces reference the same underlying font,
handling either being null (treating null as the default font)
@@ -147,11 +149,11 @@
protected:
/** uniqueID must be unique (please!) and non-zero
*/
- SkTypeface(Style style, uint32_t uniqueID, bool isFixedWidth = false)
- : fUniqueID(uniqueID), fStyle(style), fIsFixedWidth(isFixedWidth) {}
+ SkTypeface(Style style, SkFontID uniqueID, bool isFixedWidth = false);
+ virtual ~SkTypeface();
private:
- uint32_t fUniqueID;
+ SkFontID fUniqueID;
Style fStyle;
bool fIsFixedWidth;
diff --git a/samplecode/SampleAll.cpp b/samplecode/SampleAll.cpp
index 17b2829..f57bf38 100644
--- a/samplecode/SampleAll.cpp
+++ b/samplecode/SampleAll.cpp
@@ -343,23 +343,9 @@
#endif
}
-static void test_math()
-{
- float x;
- const float PI = 3.141593f;
-
- for (x = 0; x < 1; x += 0.05f)
- printf("atan(%g) = %g\n", x, atanf(x) * 180/PI);
- for (x = 1; x < 10000000; x *= 2)
- printf("atan(%g) = %g\n", x, atanf(x) * 180/PI);
-}
-
class DemoView : public SkView {
public:
- DemoView()
- {
- test_math();
- }
+ DemoView() {}
protected:
// overrides from SkEventSink
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index 88c7f4b..266264e 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -1337,12 +1337,34 @@
return this->INHERITED::onQuery(evt);
}
+#define TEST_GPIPEx
+#include "SkGPipe.h"
+
void SampleView::onDraw(SkCanvas* canvas) {
this->onDrawBackground(canvas);
+
+#ifdef TEST_GPIPE
+ SkGPipeWriter writer;
+ SkCanvas* origCanvas = canvas;
+ canvas = writer.startRecording();
+#endif
+
for (int i = 0; i < fRepeatCount; i++) {
SkAutoCanvasRestore acr(canvas, true);
this->onDrawContent(canvas);
}
+
+#ifdef TEST_GPIPE
+ writer.endRecording();
+
+ size_t size = writer.flatten(NULL);
+ SkAutoMalloc storage(size);
+ writer.flatten(storage.get());
+
+ SkGPipeReader reader(origCanvas);
+ SkGPipeReader::Status status = reader.playback(storage.get(), size);
+ SkASSERT(SkGPipeReader::kDone_Status == status);
+#endif
}
void SampleView::onDrawBackground(SkCanvas* canvas) {
diff --git a/samplecode/SampleDraw.cpp b/samplecode/SampleDraw.cpp
index 39a64cf..54070d1 100644
--- a/samplecode/SampleDraw.cpp
+++ b/samplecode/SampleDraw.cpp
@@ -4,6 +4,30 @@
#include "SkGraphics.h"
#include "SkRandom.h"
+static void test_clearonlayers(SkCanvas* canvas) {
+ SkCanvas& c = *canvas;
+
+ SkPaint paint;
+ paint.setColor(SK_ColorBLUE);
+ paint.setStyle(SkPaint::kStrokeAndFill_Style);
+ SkRect rect = SkRect::MakeXYWH(25, 25, 50, 50);
+ c.drawRect(rect, paint);
+
+ c.clipRect(rect);
+
+ c.saveLayer(NULL, NULL);
+ rect = SkRect::MakeXYWH(50, 10, 40, 80);
+ c.clipRect(rect, SkRegion::kUnion_Op);
+
+ rect = SkRect::MakeXYWH(50, 0, 50, 100);
+ // You might draw something here, but it's not necessary.
+ // paint.setColor(SK_ColorRED);
+ // c.drawRect(rect, paint);
+ paint.setXfermodeMode(SkXfermode::kClear_Mode);
+ c.drawRect(rect, paint);
+ c.restore();
+}
+
static void test_strokerect(SkCanvas* canvas, const SkRect& r) {
SkPaint p;
@@ -277,8 +301,8 @@
virtual void onDraw(SkCanvas* canvas) {
this->drawBG(canvas);
- // test_strokerect(canvas);
- // return;
+ test_clearonlayers(canvas); return;
+ // test_strokerect(canvas); return;
for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
(*iter)->draw(canvas);
diff --git a/samplecode/SampleFontScalerTest.cpp b/samplecode/SampleFontScalerTest.cpp
index c481503..0b0d349 100644
--- a/samplecode/SampleFontScalerTest.cpp
+++ b/samplecode/SampleFontScalerTest.cpp
@@ -29,7 +29,7 @@
static const int gFaceCount = SK_ARRAY_COUNT(gFaces);
-class FontScalerTestView : public SkView {
+class FontScalerTestView : public SampleView {
SkTypeface* fFaces[gFaceCount];
public:
@@ -38,6 +38,7 @@
fFaces[i] = SkTypeface::CreateFromName(gFaces[i].fName,
gFaces[i].fStyle);
}
+ this->setBGColor(0xFFDDDDDD);
}
virtual ~FontScalerTestView() {
@@ -56,13 +57,7 @@
return this->INHERITED::onQuery(evt);
}
- void drawBG(SkCanvas* canvas) {
- canvas->drawColor(0xFFDDDDDD);
- }
-
- virtual void onDraw(SkCanvas* canvas) {
- this->drawBG(canvas);
-
+ virtual void onDrawContent(SkCanvas* canvas) {
SkPaint paint;
// test handling of obscene cubic values (currently broken)
diff --git a/samplecode/SampleLines.cpp b/samplecode/SampleLines.cpp
index 4d05a9a..24291f3 100644
--- a/samplecode/SampleLines.cpp
+++ b/samplecode/SampleLines.cpp
@@ -25,30 +25,7 @@
class LinesView : public SkView {
public:
- LinesView()
- {
- unsigned r = 0x1F;
- unsigned g = 0x3F;
- for (unsigned a = 0; a <= 0xF; a++) {
- unsigned scale = 16 - SkAlpha15To16(a);
- unsigned sr = (a << 1) | (a >> 3);
- unsigned dr = r * scale >> 4;
- unsigned sg = (a << 2) | (a >> 2);
- unsigned dg = g * scale >> 4;
-
- unsigned ssg = sg & ~(~(a >> 3) & 1);
-
- printf("4444 sa=%d sr=%d sg=%d da=%d dr=%d dg=%d total-r=%d total-g=%d %d\n",
- a, sr, sg, scale, dr, dg, sr+dr, sg+dg, ssg+dg);
- }
-
- for (unsigned aa = 0; aa <= 0xFF; aa++) {
- unsigned invScale = SkAlpha255To256(255 - aa);
- unsigned dst = SkAlphaMul(0xFF, invScale);
- printf("8888 sa=%02x dst=%02x sum=%d %s\n", aa, dst, aa+dst,
- (aa+dst) > 0xFF ? "OVERFLOW" : "");
- }
- }
+ LinesView() {}
protected:
// overrides from SkEventSink
diff --git a/samplecode/SamplePicture.cpp b/samplecode/SamplePicture.cpp
index 6c018b7..00a9d2e 100644
--- a/samplecode/SamplePicture.cpp
+++ b/samplecode/SamplePicture.cpp
@@ -33,7 +33,7 @@
protected:
virtual void onDraw(SkCanvas* canvas) {
- SkDebugf("---- sc %d\n", canvas->getSaveCount() - 1);
+ // SkDebugf("---- sc %d\n", canvas->getSaveCount() - 1);
}
private:
diff --git a/samplecode/SamplePolyToPoly.cpp b/samplecode/SamplePolyToPoly.cpp
index 4b6686d..ccfe430 100644
--- a/samplecode/SamplePolyToPoly.cpp
+++ b/samplecode/SamplePolyToPoly.cpp
@@ -19,7 +19,6 @@
bool success;
success = m1.setPolyToPoly(src, dst, 3);
- SkDebugf("--- setPolyToPoly1 %d\n", success);
m2.reset();
m2.set(SkMatrix::kMScaleX, dst[1].fX - dst[0].fX);
@@ -40,7 +39,6 @@
};
success = m2.setPolyToPoly((const SkPoint*)src1, (SkPoint*)dst1, 4);
- SkDebugf("--- setPolyToPoly2 %d\n", success);
{
const SkPoint src[] = {
@@ -57,8 +55,8 @@
SkMatrix m0, m1;
m0.setPolyToPoly(src, dst, 3);
// SkSetPoly3To3(&m1, src, dst);
- m0.dump();
- m1.dump();
+ // m0.dump();
+ // m1.dump();
}
}
}
diff --git a/samplecode/SampleText.cpp b/samplecode/SampleText.cpp
index c1090ee..459923a 100644
--- a/samplecode/SampleText.cpp
+++ b/samplecode/SampleText.cpp
@@ -138,7 +138,7 @@
mm = m;
}
- int length2 = paint.breakText(text, length, width, &mm);
+ SkDEBUGCODE(int length2 =) paint.breakText(text, length, width, &mm);
SkASSERT(length2 == length);
SkASSERT(mm == width);
}
@@ -222,12 +222,6 @@
{ "Subpixel", SkPaint::kSubpixelText_Flag, true }
};
-#ifdef SK_DEBUG
- #define REPEAT_COUNT 1
-#else
- #define REPEAT_COUNT 5
-#endif
-
static int count_char_points(const SkPaint& paint, char c)
{
SkPath path;
@@ -488,210 +482,8 @@
virtual void onDraw(SkCanvas* canvas)
{
- inval(NULL);
- if (false)
- {
- canvas->translate(SkIntToScalar(480), 0);
- canvas->rotate(SkIntToScalar(90));
- }
-
this->drawBG(canvas);
- if (false)
- {
- SkPaint p;
-
- p.setAntiAlias(true);
- p.setSubpixelText(true);
- // p.setLinearText(true);
-
- SkScalar size = SkIntToScalar(6);
- SkMSec dur = 0;
- const int LOOP = 16;
- const int TIMES = 10;
-
- for (int times = 0; times < TIMES; times++)
- {
- SkMSec now = SkTime::GetMSecs();
- for (int loop = 0; loop < LOOP; loop++)
- {
- p.setTextSize(size);
- size += SK_Scalar1/5;
- canvas->drawText("Hamburgefons", 12, SkIntToScalar(10), SkIntToScalar(50), p);
- }
- dur += SkTime::GetMSecs() - now;
- SkGraphics::SetFontCacheUsed(0);
- }
-
- printf("----- duration = %g\n", dur * 1.0 / TIMES);
- this->inval(NULL);
- return;
- }
-
- if (false)
- {
- SkPaint p;
- p.setAntiAlias(true);
- for (int i = 6; i <= 36; i++)
- {
- SkRect r;
- SkPaint::FontMetrics m;
- p.setTextSize(SkIntToScalar(i));
- p.getFontMetrics(&m);
- int ascent = SkScalarRound(m.fAscent);
- int descent = SkScalarRound(m.fDescent);
- for (uint8_t c = ' '; c <= 127; c++)
- {
- p.getTextWidths(&c, 1, NULL, &r);
- if (SkScalarRound(r.fTop) < ascent)
- printf("PS %d --- %c [%d] top=%g, ascent=%g ymax=%g\n", i, c, c,
- SkScalarToFloat(r.fTop), SkScalarToFloat(m.fAscent), SkScalarToFloat(m.fTop));
- if (SkScalarRound(r.fBottom) > descent)
- printf("PS %d --- %c [%d] bottom=%g, descent=%g ymin=%g\n", i, c, c,
- SkScalarToFloat(r.fBottom), SkScalarToFloat(m.fDescent), SkScalarToFloat(m.fBottom));
- }
- }
- }
-
- if (false)
- {
- SkPaint p;
- p.setShader(fGradient);
-
-#ifdef SK_RELEASE
- SkMSec now = SkTime::GetMSecs();
- for (int i = 0; i < 100; i++)
-#endif
- canvas->drawPaint(p);
-#ifdef SK_RELEASE
- printf("----- %d ms\n", SkTime::GetMSecs() - now);
- this->inval(NULL);
-#endif
- return;
- }
-
- if (false)
- {
- SkBitmap bm;
-
- make_textstrip(&bm);
- canvas->translate(0, SkIntToScalar(50));
- for (int i = 0; i < 10; i++)
- {
- float gamma = 1 + i * 0.2f;
- SkPowerMode mode(SkFloatToScalar(1 / gamma));
- SkPaint p;
- p.setXfermode(&mode);
-
- canvas->drawBitmap(bm, 0, SkIntToScalar(i) * bm.height(), &p);
- }
- return;
- }
-
- if (false)
- {
- SkPaint paint;
-
- paint.setAntiAlias(true);
- paint.setDevKernText(true);
- SkMSec now = SkTime::GetMSecs();
- for (int i = 0; i < 1000000; i++)
- {
- paint.measureText("Hamburgefons", 15, NULL, NULL);
- }
- printf("--------- measure %d\n", SkTime::GetMSecs() - now);
- this->inval(NULL);
- return;
- }
-
- if (false)
- {
- SkRegion rgn;
- SkPath path;
- SkPaint paint;
-
- // make_badrgn(&rgn, -2);
-
- if (false)
- {
- paint.setColor(SK_ColorBLUE);
- canvas->drawIRect(rgn.getBounds(), paint);
- }
- paint.setColor(SK_ColorRED);
- draw_rgn(rgn, canvas, paint);
-
- rgn.getBoundaryPath(&path);
- paint.setARGB(0x80, 0, 0, 0xFF);
- canvas->drawPath(path, paint);
- return;
- }
-
- if (false)
- {
- SkRect r = { SkIntToScalar(50), SkIntToScalar(50), SkIntToScalar(300), SkIntToScalar(300) };
- SkPaint p;
-
- p.setStyle(SkPaint::kStroke_Style);
- p.setAlpha(0x80);
- p.setStrokeWidth(SkIntToScalar(20));
- canvas->drawRect(r, p);
- }
-
- if (false)
- {
- SkPaint p;
- SkRect r = { SkIntToScalar(100), SkIntToScalar(100), SkIntToScalar(104), SkIntToScalar(104) };
- // r.offset(SK_ScalarHalf, SK_ScalarHalf);
- p.setStyle(SkPaint::kStroke_Style);
- p.setStrokeWidth(SK_Scalar1*2);
- // p.setAntiAliasOn(true);
- canvas->drawRect(r, p);
- return;
- }
-
- if (false)
- {
- Sk64 aa, bb;
- int64_t a = (int64_t)6062080 * -30596;
- int64_t b = (int64_t)4816896 * 57957;
- aa.setMul(6062080, -30596);
- bb.setMul(4816896, 57957);
-
- a += b;
- b = a >> 16;
-
-// SkFixed c = aa.addGetFixed(bb);
-
- printf("%d %d\n", (int)a, a >> 32);
-
- SkBitmap bm;
- SkPaint paint;
- SkScalar scale = SkFloatToScalar(0.5625f);
- SkScalar x = SkIntToScalar(100);
- SkScalar y = SkIntToScalar(100);
-
- //paint.setFilterType(SkPaint::kBilinear_FilterType);
-
- SkImageDecoder::DecodeFile("/app_web_browser.png", &bm);
-
- // canvas->drawBitmap(bm, x, y, paint);
- x += SkIntToScalar(100);
- canvas->save();
- canvas->translate(x, y);
- canvas->scale(SkIntToScalar(2)/1, SkIntToScalar(2)/1);
- canvas->translate(-x, -y);
- canvas->drawBitmap(bm, x, y, &paint);
- canvas->restore();
- x += SkIntToScalar(100);
- canvas->save();
- canvas->translate(x, y);
- canvas->scale(scale, scale);
- canvas->translate(-x, -y);
- // canvas->drawBitmap(bm, x, y, paint);
- canvas->restore();
- return;
- }
-
SkAutoCanvasRestore restore(canvas, false);
{
SkRect r;
@@ -713,10 +505,6 @@
paint.setAntiAlias(true);
paint.setFlags(paint.getFlags() | gHints[index].fFlags);
- SkMSec now = 0;
- if (REPEAT_COUNT > 1)
- now = SkTime::GetMSecs();
-
SkRect clip;
clip.set(SkIntToScalar(25), SkIntToScalar(34), SkIntToScalar(88), SkIntToScalar(155));
@@ -743,26 +531,17 @@
}
#endif
- for (int j = 0; j < REPEAT_COUNT; j++)
- {
- SkScalar y = SkIntToScalar(0);
- for (int i = 9; i <= 24; i++) {
- paint.setTextSize(SkIntToScalar(i) /*+ (gRand.nextU() & 0xFFFF)*/);
- for (SkScalar dx = 0; dx <= SkIntToScalar(3)/4; dx += SkIntToScalar(1) /* /4 */)
- {
- y += paint.getFontSpacing();
- DrawTheText(canvas, text, length, SkIntToScalar(20) + dx, y, paint, fClickX, fMF);
- }
- }
- if (gHints[index].fFlushCache) {
-// SkGraphics::SetFontCacheUsed(0);
+ SkScalar y = SkIntToScalar(0);
+ for (int i = 9; i <= 24; i++) {
+ paint.setTextSize(SkIntToScalar(i) /*+ (gRand.nextU() & 0xFFFF)*/);
+ for (SkScalar dx = 0; dx <= SkIntToScalar(3)/4; dx += SkIntToScalar(1) /* /4 */)
+ {
+ y += paint.getFontSpacing();
+ DrawTheText(canvas, text, length, SkIntToScalar(20) + dx, y, paint, fClickX, fMF);
}
}
-
- if (REPEAT_COUNT > 1)
- {
- printf("--------- FPS = %g\n", REPEAT_COUNT * 1000. / (SkTime::GetMSecs() - now));
- this->inval(NULL);
+ if (gHints[index].fFlushCache) {
+// SkGraphics::SetFontCacheUsed(0);
}
}
diff --git a/samplecode/SampleTypeface.cpp b/samplecode/SampleTypeface.cpp
index 5442e5f..63f1d5a 100644
--- a/samplecode/SampleTypeface.cpp
+++ b/samplecode/SampleTypeface.cpp
@@ -13,6 +13,7 @@
#include "SkColorPriv.h"
#include "SkColorFilter.h"
#include "SkDither.h"
+#include "SkTypefaceCache.h"
static int dither_4444(int x) {
return ((x << 1) - ((x >> 4 << 4) | (x >> 4))) >> 4;
@@ -82,6 +83,8 @@
for (int i = 0; i < gFaceCount; i++) {
SkSafeUnref(fFaces[i]);
}
+
+ SkTypefaceCache::Dump();
}
protected:
@@ -99,11 +102,6 @@
paint.setAntiAlias(true);
paint.setTextSize(SkIntToScalar(30));
- if (false) {
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(SkIntToScalar(1));
- }
-
const char* text = "Hamburgefons";
const size_t textLen = strlen(text);
@@ -111,50 +109,12 @@
SkScalar dy = paint.getFontMetrics(NULL);
SkScalar y = dy;
+ paint.setLinearText(true);
for (int i = 0; i < gFaceCount; i++) {
paint.setTypeface(fFaces[i]);
canvas->drawText(text, textLen, x, y, paint);
y += dy;
}
-
- SkRect r;
- if (false) {
- r.set(10, 10, 100, 100);
- paint.setStyle(SkPaint::kStrokeAndFill_Style);
- paint.setColor(SK_ColorBLUE);
- paint.setStrokeWidth(1);
- canvas->drawRect(r, paint);
- paint.setStrokeWidth(0);
- }
-
- if (false) {
- r.set(294912.75f, 294912.75f, 884738.25f, 884738.25f);
- canvas->scale(2.4414E-4f, 2.4414E-4f);
- paint.setStyle(SkPaint::kFill_Style);
- canvas->drawRect(r, paint);
- }
-
- if (false) {
- SkScalar rad = 90;
- SkScalar angle = 210;
- SkScalar cx = 150;
- SkScalar cy = 105;
- r.set(cx - rad, cy - rad, cx + rad, cy + rad);
- SkPath path;
- path.arcTo(r, angle, -(angle + 90), true);
- path.close();
-
- paint.setColor(SK_ColorRED);
- canvas->drawRect(path.getBounds(), paint);
- paint.setColor(SK_ColorBLUE);
- canvas->drawPath(path, paint);
-
- paint.setColor(SK_ColorGREEN);
- SkPoint pts[100];
- int count = path.getPoints(pts, 100);
- paint.setStrokeWidth(5);
- canvas->drawPoints(SkCanvas::kPoints_PointMode, count, pts, paint);
- }
}
private:
diff --git a/src/core/SkBlitter_ARGB32.cpp b/src/core/SkBlitter_ARGB32.cpp
index d923315..361d6b6 100644
--- a/src/core/SkBlitter_ARGB32.cpp
+++ b/src/core/SkBlitter_ARGB32.cpp
@@ -40,14 +40,16 @@
///////////////////////////////////////////////////////////////////////////////
-static int upscale31To256(int value) {
+static inline int upscale31To32(int value) {
SkASSERT((unsigned)value <= 31);
- // 0..31 -> 0..255
- value = (value << 3) | (value >> 2);
- // 0..255 -> 0..256
- value += (value >> 7);
- SkASSERT((unsigned)value <= 256);
- return value;
+ return value + (value >> 4);
+}
+
+static inline unsigned blend32(unsigned src, unsigned dst, unsigned scale) {
+ SkASSERT(src <= 0xFF);
+ SkASSERT(dst <= 0xFF);
+ SkASSERT(scale <= 32);
+ return dst + ((src - dst) * scale >> 5);
}
static void blit_lcd16_opaque(SkPMColor dst[], const uint16_t src[],
@@ -62,6 +64,8 @@
continue;
}
+ SkPMColor d = dst[i];
+
/* We want all of these in 5bits, hence the shifts in case one of them
* (green) is 6bits.
*/
@@ -70,22 +74,21 @@
int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
// Now upscale them to 0..256, so we can use SkAlphaBlend
- maskR = upscale31To256(maskR);
- maskG = upscale31To256(maskG);
- maskB = upscale31To256(maskB);
+ maskR = upscale31To32(maskR);
+ maskG = upscale31To32(maskG);
+ maskB = upscale31To32(maskB);
int maskA = SkMax32(SkMax32(maskR, maskG), maskB);
- SkPMColor d = dst[i];
int dstA = SkGetPackedA32(d);
int dstR = SkGetPackedR32(d);
int dstG = SkGetPackedG32(d);
int dstB = SkGetPackedB32(d);
- dst[i] = SkPackARGB32(SkAlphaBlend(0xFF, dstA, maskA),
- SkAlphaBlend(srcR, dstR, maskR),
- SkAlphaBlend(srcG, dstG, maskG),
- SkAlphaBlend(srcB, dstB, maskB));
+ dst[i] = SkPackARGB32(blend32(0xFF, dstA, maskA),
+ blend32(srcR, dstR, maskR),
+ blend32(srcG, dstG, maskG),
+ blend32(srcB, dstB, maskB));
}
}
diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp
index 9a764fc..03610d2 100644
--- a/src/core/SkTypeface.cpp
+++ b/src/core/SkTypeface.cpp
@@ -18,6 +18,29 @@
#include "SkTypeface.h"
#include "SkFontHost.h"
+#define TRACE_LIFECYCLE
+
+#ifdef TRACE_LIFECYCLE
+ static int32_t gTypefaceCounter;
+#endif
+
+SkTypeface::SkTypeface(Style style, SkFontID fontID, bool isFixedWidth)
+ : fUniqueID(fontID), fStyle(style), fIsFixedWidth(isFixedWidth) {
+#ifdef TRACE_LIFECYCLE
+ SkDebugf("SkTypeface: create %p fontID %d total %d\n",
+ this, fontID, ++gTypefaceCounter);
+#endif
+}
+
+SkTypeface::~SkTypeface() {
+#ifdef TRACE_LIFECYCLE
+ SkDebugf("SkTypeface: destroy %p fontID %d total %d\n",
+ this, fUniqueID, --gTypefaceCounter);
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
uint32_t SkTypeface::UniqueID(const SkTypeface* face) {
if (face) {
return face->uniqueID();
diff --git a/src/core/SkTypefaceCache.cpp b/src/core/SkTypefaceCache.cpp
new file mode 100644
index 0000000..4db6bfb
--- /dev/null
+++ b/src/core/SkTypefaceCache.cpp
@@ -0,0 +1,121 @@
+/*
+ Copyright 2011 Google Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+
+#include "SkTypefaceCache.h"
+#include "SkThread.h"
+
+#define TYPEFACE_CACHE_LIMIT 128
+
+void SkTypefaceCache::add(SkTypeface* face, SkTypeface::Style requestedStyle) {
+ if (fArray.count() >= TYPEFACE_CACHE_LIMIT) {
+ this->purge(TYPEFACE_CACHE_LIMIT >> 2);
+ }
+
+ Rec* rec = fArray.append();
+ rec->fFace = face;
+ rec->fRequestedStyle = requestedStyle;
+ face->ref();
+}
+
+SkTypeface* SkTypefaceCache::findByID(SkFontID fontID) const {
+ const Rec* curr = fArray.begin();
+ const Rec* stop = fArray.end();
+ while (curr < stop) {
+ if (curr->fFace->uniqueID() == fontID) {
+ return curr->fFace;
+ }
+ curr += 1;
+ }
+ return NULL;
+}
+
+SkTypeface* SkTypefaceCache::findByProc(FindProc proc, void* ctx) const {
+ const Rec* curr = fArray.begin();
+ const Rec* stop = fArray.end();
+ while (curr < stop) {
+ if (proc(curr->fFace, curr->fRequestedStyle, ctx)) {
+ return curr->fFace;
+ }
+ curr += 1;
+ }
+ return NULL;
+}
+
+void SkTypefaceCache::purge(int numToPurge) {
+ int count = fArray.count();
+ int i = 0;
+ while (i < count) {
+ SkTypeface* face = fArray[i].fFace;
+ if (1 == face->getRefCnt()) {
+ face->unref();
+ fArray.remove(i);
+ --count;
+ if (--numToPurge == 0) {
+ return;
+ }
+ } else {
+ ++i;
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkTypefaceCache& SkTypefaceCache::Get() {
+ static SkTypefaceCache gCache;
+ return gCache;
+}
+
+SkFontID SkTypefaceCache::NewFontID() {
+ static int32_t gFontID;
+ return sk_atomic_inc(&gFontID) + 1;
+}
+
+static SkMutex gMutex;
+
+void SkTypefaceCache::Add(SkTypeface* face, SkTypeface::Style requestedStyle) {
+ SkAutoMutexAcquire ama(gMutex);
+ Get().add(face, requestedStyle);
+}
+
+SkTypeface* SkTypefaceCache::FindByID(SkFontID fontID) {
+ SkAutoMutexAcquire ama(gMutex);
+ return Get().findByID(fontID);
+}
+
+SkTypeface* SkTypefaceCache::FindByProc(FindProc proc, void* ctx) {
+ SkAutoMutexAcquire ama(gMutex);
+ return Get().findByProc(proc, ctx);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef SK_DEBUG
+static bool DumpProc(SkTypeface* face, SkTypeface::Style style, void* ctx) {
+ SkDebugf("SkTypefaceCache: face %p fontID %d style %d refcnt %d\n",
+ face, face->uniqueID(), style, face->getRefCnt());
+ return false;
+}
+#endif
+
+void SkTypefaceCache::Dump() {
+#ifdef SK_DEBUG
+ SkAutoMutexAcquire ama(gMutex);
+ (void)Get().findByProc(DumpProc, NULL);
+#endif
+}
+
diff --git a/src/core/SkTypefaceCache.h b/src/core/SkTypefaceCache.h
new file mode 100644
index 0000000..91411a4
--- /dev/null
+++ b/src/core/SkTypefaceCache.h
@@ -0,0 +1,82 @@
+/*
+ Copyright 2011 Google Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+
+#ifndef SkTypefaceCache_DEFINED
+#define SkTypefaceCache_DEFINED
+
+#include "SkTypeface.h"
+#include "SkTDArray.h"
+
+/* TODO
+ * Provide std way to cache name+requestedStyle aliases to the same typeface.
+ *
+ * The current mechanism ends up create a diff typeface for each one, even if
+ * they map to the same internal obj (e.g. CTFontRef on the mac)
+ */
+
+class SkTypefaceCache {
+public:
+ typedef bool (*FindProc)(SkTypeface*, SkTypeface::Style, void* context);
+
+ /**
+ * Helper: returns a unique fontID to pass to the constructor of
+ * your subclass of SkTypeface
+ */
+ static SkFontID NewFontID();
+
+ /**
+ * Add a typeface to the cache. This ref()s the typeface, so that the
+ * cache is also an owner. Later, if we need to purge the cache, it will
+ * unref() typefaces whose refcnt is 1 (meaning only the cache is an owner).
+ */
+ static void Add(SkTypeface*, SkTypeface::Style requested);
+
+ /**
+ * Search the cache for a typeface with the specified fontID (uniqueID).
+ * If one is found, return it (its reference count is unmodified). If none
+ * is found, return NULL.
+ */
+ static SkTypeface* FindByID(SkFontID fontID);
+
+ /**
+ * Iterate through the cache, calling proc(typeface, ctx) with each
+ * typeface. If proc returns true, then we return that typeface (its
+ * reference count is unmodified). If it never returns true, we return NULL.
+ */
+ static SkTypeface* FindByProc(FindProc proc, void* ctx);
+
+ /**
+ * Debugging only: dumps the status of the typefaces in the cache
+ */
+ static void Dump();
+
+private:
+ static SkTypefaceCache& Get();
+
+ void add(SkTypeface*, SkTypeface::Style requested);
+ SkTypeface* findByID(SkFontID findID) const;
+ SkTypeface* findByProc(FindProc proc, void* ctx) const;
+ void purge(int count);
+
+ struct Rec {
+ SkTypeface* fFace;
+ SkTypeface::Style fRequestedStyle;
+ };
+ SkTDArray<Rec> fArray;
+};
+
+#endif
diff --git a/src/ports/SkFontHost_mac_coretext.cpp b/src/ports/SkFontHost_mac_coretext.cpp
index cdf3eb3..82bde7b 100644
--- a/src/ports/SkFontHost_mac_coretext.cpp
+++ b/src/ports/SkFontHost_mac_coretext.cpp
@@ -23,23 +23,11 @@
#include "SkString.h"
#include "SkTypeface_mac.h"
#include "SkUtils.h"
-
-
-static const SkFontID kSkInvalidFontID = 0;
+#include "SkTypefaceCache.h"
static const size_t FONT_CACHE_MEMORY_BUDGET = 1024 * 1024;
static const char FONT_DEFAULT_NAME[] = "Lucida Sans";
-typedef struct {
- SkString name;
- SkTypeface::Style style;
- SkFontID fontID;
- CTFontRef fontRef;
-} SkNativeFontInfo;
-
-typedef std::vector<SkNativeFontInfo> SkNativeFontInfoList;
-typedef SkNativeFontInfoList::iterator SkNativeFontInfoListIterator;
-
//============================================================================
// Macros
//----------------------------------------------------------------------------
@@ -74,233 +62,193 @@
return (SkTypeface::Style)style;
}
-
-//============================================================================
-// SkNativeFontCache
-//----------------------------------------------------------------------------
-#pragma mark -
-class SkNativeFontCache {
+class SkTypeface_Mac : public SkTypeface {
public:
- SkNativeFontCache(void);
- virtual ~SkNativeFontCache(void);
+ SkTypeface_Mac(SkTypeface::Style style, SkFontID fontID, bool isMonospace)
+ : SkTypeface(style, fontID, isMonospace), fFontRef(0) {}
- bool IsValid(SkFontID fontID);
- CTFontRef GetFont(SkFontID fontID);
- SkNativeFontInfo GetFontInfo(const char familyName[], SkTypeface::Style);
- SkNativeFontInfo CreateFont(const char familyName[], SkTypeface::Style);
- SkNativeFontInfo CreateFromCTFont(CTFontRef);
+ virtual ~SkTypeface_Mac() { CFRelease(fFontRef); }
- static SkNativeFontCache* Get(void);
-
-private:
- CTFontRef CreateNativeFont(const char familyName[], SkTypeface::Style style);
-
-
-private:
- SkNativeFontInfoList mFonts;
- SkMutex mMutex;
+ SkString fName;
+ CTFontRef fFontRef;
};
-SkNativeFontCache::SkNativeFontCache(void)
-{ SkAutoMutexAcquire acquireLock(mMutex);
- SkNativeFontInfo fontInfo;
-
-
- // Initialise ourselves
- //
- // SkTypeface uses a uint32_t to identify fonts, however CoreText font references
- // are opaque pointers.
- //
- // To support 64-bit builds, we need a separate index to look up a 64-bit font
- // reference from its 32-bit SkFontID. As an ID of 0 is reserved, we insert a
- // dummy entry into the cache so we can use the array index as the font ID.
- //
- // This could be simplified if SkFontID was changed to a intptr_t, and SkTypeface
- // returned an SkFontID from uniqueID().
- fontInfo.name = SkString("__SkNativeFontCache__");
- fontInfo.style = SkTypeface::kNormal;
- fontInfo.fontID = kSkInvalidFontID;
- fontInfo.fontRef = NULL;
-
- mFonts.push_back(fontInfo);
+static SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[]) {
+ bool isMonospace;
+ SkTypeface::Style style = computeStyleBits(fontRef, &isMonospace);
+ SkTypeface_Mac* face = new SkTypeface_Mac(style,
+ SkTypefaceCache::NewFontID(),
+ isMonospace);
+ face->fFontRef = fontRef; // we take over ownership of fontRef
+ face->fName.set(name);
+ return face;
}
-SkNativeFontCache::~SkNativeFontCache(void)
-{ SkAutoMutexAcquire acquireLock(mMutex);
- SkNativeFontInfoListIterator theIter;
-
-
- // Clean up
- for (theIter = mFonts.begin(); theIter != mFonts.end(); theIter++)
- CFSafeRelease(theIter->fontRef);
-}
-
-bool SkNativeFontCache::IsValid(SkFontID fontID)
-{ SkAutoMutexAcquire acquireLock(mMutex);
- bool isValid;
-
-
- // Check the ID
- isValid = (fontID >= 1 && fontID < mFonts.size());
- return(isValid);
-}
-
-CTFontRef SkNativeFontCache::GetFont(SkFontID fontID)
-{ SkAutoMutexAcquire acquireLock(mMutex);
-
-
- // Validate our parameters
- SkASSERT(fontID >= 1 && fontID < mFonts.size());
-
-
- // Get the font
- return(mFonts.at(fontID).fontRef);
-}
-
-SkNativeFontInfo SkNativeFontCache::GetFontInfo(const char familyName[],
- SkTypeface::Style theStyle)
-{ SkAutoMutexAcquire acquireLock(mMutex);
- SkNativeFontInfo fontInfo;
- SkNativeFontInfoListIterator theIter;
-
- // Validate our parameters
- SkASSERT(familyName && *familyName);
-
- // Get the state we need
- fontInfo.style = SkTypeface::kNormal;
- fontInfo.fontID = kSkInvalidFontID;
- fontInfo.fontRef = NULL;
-
- // Get the font
- for (theIter = mFonts.begin(); theIter != mFonts.end(); theIter++) {
- if (theIter->style == theStyle && theIter->name.equals(familyName)) {
- return *theIter;
- }
- }
-
- return fontInfo;
-}
-
-SkNativeFontInfo SkNativeFontCache::CreateFont(const char familyName[],
- SkTypeface::Style theStyle) {
- SkAutoMutexAcquire acquireLock(mMutex);
- SkNativeFontInfo fontInfo;
-
-
- // Validate our parameters
- SkASSERT(familyName && *familyName);
-
-
- // Create the font
- fontInfo.name.set(familyName);
- fontInfo.fontID = mFonts.size();
- fontInfo.fontRef = CreateNativeFont(familyName, theStyle);
- fontInfo.style = computeStyleBits(fontInfo.fontRef, NULL);
-
- mFonts.push_back(fontInfo);
- return(fontInfo);
-}
-
-SkNativeFontInfo SkNativeFontCache::CreateFromCTFont(CTFontRef font) {
- SkAutoMutexAcquire acquireLock(mMutex);
- SkNativeFontInfo fontInfo;
-
- // TODO: need to query the font's name
-// fontInfo.name.set(familyName);
- fontInfo.fontID = mFonts.size();
- fontInfo.fontRef = font;
- CFRetain(font);
- fontInfo.style = computeStyleBits(font, NULL);
-
- mFonts.push_back(fontInfo);
- return(fontInfo);
-}
-
-SkNativeFontCache *SkNativeFontCache::Get(void) {
- static SkNativeFontCache sInstance;
- // We use a local static for well-defined static initialisation order.
- return &sInstance;
-}
-
-///////////////////////////////////////////////////////////////////////////
-
-CTFontRef SkNativeFontCache::CreateNativeFont(const char familyName[],
- SkTypeface::Style theStyle) {
+static SkTypeface* NewFromName(const char familyName[],
+ SkTypeface::Style theStyle) {
CFMutableDictionaryRef cfAttributes, cfTraits;
CFNumberRef cfFontTraits;
CTFontSymbolicTraits ctFontTraits;
CTFontDescriptorRef ctFontDesc;
CFStringRef cfFontName;
CTFontRef ctFont;
-
-
+
+
// Get the state we need
ctFontDesc = NULL;
ctFont = NULL;
ctFontTraits = 0;
-
- if (theStyle & SkTypeface::kBold)
+
+ if (theStyle & SkTypeface::kBold) {
ctFontTraits |= kCTFontBoldTrait;
+ }
- if (theStyle & SkTypeface::kItalic)
+ if (theStyle & SkTypeface::kItalic) {
ctFontTraits |= kCTFontItalicTrait;
-
-
+ }
+
// Create the font info
cfFontName = CFStringCreateWithCString(NULL, familyName, kCFStringEncodingUTF8);
cfFontTraits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits);
cfAttributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
cfTraits = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-
-
+
+
// Create the font
if (cfFontName != NULL && cfFontTraits != NULL && cfAttributes != NULL && cfTraits != NULL) {
CFDictionaryAddValue(cfTraits, kCTFontSymbolicTrait, cfFontTraits);
-
+
CFDictionaryAddValue(cfAttributes, kCTFontFamilyNameAttribute, cfFontName);
CFDictionaryAddValue(cfAttributes, kCTFontTraitsAttribute, cfTraits);
-
+
ctFontDesc = CTFontDescriptorCreateWithAttributes(cfAttributes);
if (ctFontDesc != NULL) {
ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL);
}
}
-
+
CFSafeRelease(cfFontName);
CFSafeRelease(cfFontTraits);
CFSafeRelease(cfAttributes);
CFSafeRelease(cfTraits);
CFSafeRelease(ctFontDesc);
- return(ctFont);
+ return ctFont ? NewFromFontRef(ctFont, familyName) : NULL;
}
-//============================================================================
-// SkTypeface_Mac
-//----------------------------------------------------------------------------
-#pragma mark -
-class SkTypeface_Mac : public SkTypeface {
-public:
- SkTypeface_Mac(SkTypeface::Style style, uint32_t fontID);
+static CTFontRef GetFontRefFromFontID(SkFontID fontID) {
+ SkTypeface_Mac* face = reinterpret_cast<SkTypeface_Mac*>(SkTypefaceCache::FindByID(fontID));
+ return face ? face->fFontRef : 0;
+}
+
+static SkTypeface* GetDefaultFace() {
+ static SkTypeface* gDefaultFace;
+
+ if (NULL == gDefaultFace) {
+ gDefaultFace = new SkTypeface_Mac(SkTypeface::kNormal,
+ SkTypefaceCache::NewFontID(), false);
+ }
+ return gDefaultFace;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+struct FontRefRec {
+ CTFontRef fFontRef;
};
+static bool FindByFontRef(SkTypeface* face, SkTypeface::Style, void* ctx) {
+ const SkTypeface_Mac* mface = reinterpret_cast<SkTypeface_Mac*>(face);
+ const FontRefRec* rec = reinterpret_cast<const FontRefRec*>(ctx);
-SkTypeface_Mac::SkTypeface_Mac(SkTypeface::Style style, uint32_t fontID)
- : SkTypeface(style, fontID) {
+ return rec->fFontRef == mface->fFontRef;
}
+/* This function is visible on the outside. It first searches the cache, and if
+ * not found, returns a new entry (after adding it to the cache).
+ */
+SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef fontRef) {
+ FontRefRec rec = { fontRef };
+ SkTypeface* face = SkTypefaceCache::FindByProc(FindByFontRef, &rec);
+ if (face) {
+ face->ref();
+ } else {
+ face = NewFromFontRef(fontRef, NULL);
+ SkTypefaceCache::Add(face, face->style());
+ }
+ SkASSERT(face->getRefCnt() > 1);
+ return face;
+}
-SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef font) {
- SkNativeFontInfo info;
+struct NameStyleRec {
+ const char* fName;
+ SkTypeface::Style fStyle;
+};
+
+static bool FindByNameStyle(SkTypeface* face, SkTypeface::Style style,
+ void* ctx) {
+ const SkTypeface_Mac* mface = reinterpret_cast<SkTypeface_Mac*>(face);
+ const NameStyleRec* rec = reinterpret_cast<const NameStyleRec*>(ctx);
- info = SkNativeFontCache::Get()->CreateFromCTFont(font);
- return new SkTypeface_Mac(info.style, info.fontID);
+ return rec->fStyle == style && mface->fName.equals(rec->fName);
}
-//============================================================================
-// SkScalerContext_Mac
-//----------------------------------------------------------------------------
-#pragma mark -
+static const char* map_css_names(const char* name) {
+ static const struct {
+ const char* fFrom; // name the caller specified
+ const char* fTo; // "canonical" name we map to
+ } gPairs[] = {
+ { "sans-serif", "Helvetica" },
+ { "serif", "Times" },
+ { "monospace", "Courier" }
+ };
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
+ if (strcmp(name, gPairs[i].fFrom) == 0) {
+ return gPairs[i].fTo;
+ }
+ }
+ return name; // no change
+}
+
+SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
+ const char familyName[],
+ const void* data, size_t bytelength,
+ SkTypeface::Style style) {
+ if (familyName) {
+ familyName = map_css_names(familyName);
+ }
+
+ // Clone an existing typeface
+ // TODO: only clone if style matches the familyFace's style...
+ if (familyName == NULL && familyFace != NULL) {
+ familyFace->ref();
+ return const_cast<SkTypeface*>(familyFace);
+ }
+
+ if (!familyName || !*familyName) {
+ familyName = FONT_DEFAULT_NAME;
+ }
+
+ NameStyleRec rec = { familyName, style };
+ SkTypeface* face = SkTypefaceCache::FindByProc(FindByNameStyle, &rec);
+
+ if (face) {
+ face->ref();
+ } else {
+ face = NewFromName(familyName, style);
+ if (face) {
+ SkTypefaceCache::Add(face, style);
+ } else {
+ face = GetDefaultFace();
+ face->ref();
+ }
+ }
+ return face;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
class SkScalerContext_Mac : public SkScalerContext {
public:
SkScalerContext_Mac(const SkDescriptor* desc);
@@ -341,7 +289,7 @@
// Get the state we need
fRec.getSingleMatrix(&skMatrix);
- ctFont = SkNativeFontCache::Get()->GetFont(fRec.fFontID);
+ ctFont = GetFontRefFromFontID(fRec.fFontID);
numGlyphs = CTFontGetGlyphCount(ctFont);
SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF);
@@ -642,56 +590,7 @@
}
-static const char* map_css_names(const char* name) {
- static const struct {
- const char* fFrom;
- const char* fTo;
- } gPairs[] = {
- { "sans-serif", "Helvetica" },
- { "serif", "Times" },
- { "monospace", "Courier" }
- };
-
- for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
- if (strcmp(name, gPairs[i].fFrom) == 0) {
- return gPairs[i].fTo;
- }
- }
- return name; // no change
-}
-
-///////////////////////////////////////////////////////////////////////////
-#pragma mark -
-
-SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
- const char familyName[],
- const void* data, size_t bytelength,
- SkTypeface::Style style) {
- if (familyName) {
- familyName = map_css_names(familyName);
- }
-
- SkNativeFontCache* fontTable = SkNativeFontCache::Get();
-
- // Clone an existing typeface
- // TODO: only clone if style matches the familyFace's style...
- if (familyName == NULL && familyFace != NULL) {
- familyFace->ref();
- return const_cast<SkTypeface*>(familyFace);
- }
-
- if (!familyName || !*familyName) {
- familyName = FONT_DEFAULT_NAME;
- }
-
- // Get the native font
- SkNativeFontInfo fontInfo = fontTable->GetFontInfo(familyName, style);
- if (fontInfo.fontID == kSkInvalidFontID) {
- fontInfo = fontTable->CreateFont(familyName, style);
- }
-
- return new SkTypeface_Mac(fontInfo.style, fontInfo.fontID);
-}
+///////////////////////////////////////////////////////////////////////////////
SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream)
{
@@ -713,76 +612,50 @@
return NULL;
}
-///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
-bool SkFontHost::ValidFontID(SkFontID uniqueID)
-{
-
- // Check the font ID
- return(SkNativeFontCache::Get()->IsValid(uniqueID));
+bool SkFontHost::ValidFontID(SkFontID fontID) {
+ return SkTypefaceCache::FindByID(fontID) != NULL;
}
-SkStream* SkFontHost::OpenStream(SkFontID uniqueID)
-{
+SkStream* SkFontHost::OpenStream(SkFontID uniqueID) {
SkASSERT(!"SkFontHost::OpenStream unimplemented");
return(NULL);
}
-size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length, int32_t* index)
-{
+size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length,
+ int32_t* index) {
SkASSERT(!"SkFontHost::GetFileName unimplemented");
return(0);
}
-///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
-void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream)
-{
+void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
SkASSERT(!"SkFontHost::Serialize unimplemented");
}
-SkTypeface* SkFontHost::Deserialize(SkStream* stream)
-{
+SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
SkASSERT(!"SkFontHost::Deserialize unimplemented");
return(NULL);
}
-///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
-SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc)
-{
+SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {
return new SkScalerContext_Mac(desc);
}
-uint32_t SkFontHost::NextLogicalFont(uint32_t fontID)
-{ SkTypeface *typeFace;
- uint32_t newFontID;
-
-
- // Get the state we need
- newFontID = kSkInvalidFontID;
- typeFace = CreateTypeface(NULL, FONT_DEFAULT_NAME, NULL, 0, SkTypeface::kNormal);
-
- if (typeFace == NULL)
- return(0);
-
-
- // Get the next font
- //
- // When we're passed in the default font, we've reached the end.
- newFontID = typeFace->uniqueID();
- if (newFontID == fontID)
- newFontID = 0;
-
-
- // Clean up
- typeFace->unref();
-
- return(newFontID);
+SkFontID SkFontHost::NextLogicalFont(SkFontID fontID) {
+ SkFontID nextFontID = 0;
+ SkTypeface* face = GetDefaultFace();
+ if (face->uniqueID() != fontID) {
+ nextFontID = face->uniqueID();
+ }
+ return nextFontID;
}
-void SkFontHost::FilterRec(SkScalerContext::Rec* rec)
-{
+void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
// we only support 2 levels of hinting
SkPaint::Hinting h = rec->getHinting();
if (SkPaint::kSlight_Hinting == h) {
@@ -800,35 +673,32 @@
///////////////////////////////////////////////////////////////////////////
-size_t SkFontHost::ShouldPurgeFontCache(size_t sizeAllocatedSoFar)
-{
- if (sizeAllocatedSoFar > FONT_CACHE_MEMORY_BUDGET)
+size_t SkFontHost::ShouldPurgeFontCache(size_t sizeAllocatedSoFar) {
+ if (sizeAllocatedSoFar > FONT_CACHE_MEMORY_BUDGET) {
return sizeAllocatedSoFar - FONT_CACHE_MEMORY_BUDGET;
- else
- return 0; // nothing to do
-}
-
-int SkFontHost::ComputeGammaFlag(const SkPaint& paint)
-{
+ }
return 0;
}
-void SkFontHost::GetGammaTables(const uint8_t* tables[2])
-{
+int SkFontHost::ComputeGammaFlag(const SkPaint& paint) {
+ return 0;
+}
+
+void SkFontHost::GetGammaTables(const uint8_t* tables[2]) {
tables[0] = NULL; // black gamma (e.g. exp=1.4)
tables[1] = NULL; // white gamma (e.g. exp= 1/1.4)
}
///////////////////////////////////////////////////////////////////////////
-int SkFontHost::CountTables(SkFontID fontID)
-{ int numTables;
+int SkFontHost::CountTables(SkFontID fontID) {
+ int numTables;
CFArrayRef cfArray;
CTFontRef ctFont;
// Get the state we need
- ctFont = SkNativeFontCache::Get()->GetFont(fontID);
+ ctFont = GetFontRefFromFontID(fontID);
cfArray = CTFontCopyAvailableTables(ctFont, kCTFontTableOptionNoOptions);
numTables = 0;
@@ -850,7 +720,7 @@
// Get the state we need
- ctFont = SkNativeFontCache::Get()->GetFont(fontID);
+ ctFont = GetFontRefFromFontID(fontID);
cfArray = CTFontCopyAvailableTables(ctFont, kCTFontTableOptionNoOptions);
numTables = 0;
@@ -875,7 +745,7 @@
// Get the state we need
- ctFont = SkNativeFontCache::Get()->GetFont(fontID);
+ ctFont = GetFontRefFromFontID(fontID);
cfData = CTFontCopyTable(ctFont, (CTFontTableTag) tag, kCTFontTableOptionNoOptions);
theSize = 0;
@@ -898,7 +768,7 @@
// Get the state we need
- ctFont = SkNativeFontCache::Get()->GetFont(fontID);
+ ctFont = GetFontRefFromFontID(fontID);
cfData = CTFontCopyTable(ctFont, (CTFontTableTag) tag, kCTFontTableOptionNoOptions);
theSize = 0;
diff --git a/xcode/maccore/maccore.xcodeproj/project.pbxproj b/xcode/maccore/maccore.xcodeproj/project.pbxproj
index 7d4ccba..2dce372 100644
--- a/xcode/maccore/maccore.xcodeproj/project.pbxproj
+++ b/xcode/maccore/maccore.xcodeproj/project.pbxproj
@@ -16,6 +16,7 @@
00488AF40F86532E00C08A57 /* SkDebug_stdio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00488AF30F86532E00C08A57 /* SkDebug_stdio.cpp */; };
005B11BF12EFDC2D00A08864 /* SkFontHost_mac_coretext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27D0F41C11BD227D001B8EBE /* SkFontHost_mac_coretext.cpp */; };
007C8DC910B4694D008CDB57 /* SkUtils_opts_none.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 007C8DC810B4694D008CDB57 /* SkUtils_opts_none.cpp */; };
+ 00AB17D2136EE742004E1B73 /* SkTypefaceCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00AB17D1136EE742004E1B73 /* SkTypefaceCache.cpp */; };
27739F2B0F11407000F233EA /* SkCreateCGImageRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27739F2A0F11407000F233EA /* SkCreateCGImageRef.cpp */; };
27739F2D0F11408100F233EA /* SkImageDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27739F2C0F11408100F233EA /* SkImageDecoder.cpp */; };
/* End PBXBuildFile section */
@@ -31,6 +32,7 @@
002884E00EFABFFC0083E387 /* SkGlobals_global.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkGlobals_global.cpp; path = ../../src/ports/SkGlobals_global.cpp; sourceTree = SOURCE_ROOT; };
00488AF30F86532E00C08A57 /* SkDebug_stdio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkDebug_stdio.cpp; path = ../../src/ports/SkDebug_stdio.cpp; sourceTree = SOURCE_ROOT; };
007C8DC810B4694D008CDB57 /* SkUtils_opts_none.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkUtils_opts_none.cpp; path = ../../src/opts/SkUtils_opts_none.cpp; sourceTree = SOURCE_ROOT; };
+ 00AB17D1136EE742004E1B73 /* SkTypefaceCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkTypefaceCache.cpp; path = ../../src/core/SkTypefaceCache.cpp; sourceTree = SOURCE_ROOT; };
27739F2A0F11407000F233EA /* SkCreateCGImageRef.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkCreateCGImageRef.cpp; path = ../../src/utils/mac/SkCreateCGImageRef.cpp; sourceTree = SOURCE_ROOT; };
27739F2C0F11408100F233EA /* SkImageDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkImageDecoder.cpp; path = ../../src/images/SkImageDecoder.cpp; sourceTree = SOURCE_ROOT; };
27739F2E0F11409100F233EA /* SkImageDecoder_CG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkImageDecoder_CG.cpp; path = ../../src/ports/SkImageDecoder_CG.cpp; sourceTree = SOURCE_ROOT; };
@@ -77,6 +79,7 @@
children = (
27D0F41B11BD227D001B8EBE /* SkFontHost_mac_atsui.cpp */,
27D0F41C11BD227D001B8EBE /* SkFontHost_mac_coretext.cpp */,
+ 00AB17D1136EE742004E1B73 /* SkTypefaceCache.cpp */,
007C8DC810B4694D008CDB57 /* SkUtils_opts_none.cpp */,
00488AF30F86532E00C08A57 /* SkDebug_stdio.cpp */,
002884E00EFABFFC0083E387 /* SkGlobals_global.cpp */,
@@ -183,6 +186,7 @@
003144D50FB8491400B10956 /* SkImageDecoder_CG.cpp in Sources */,
007C8DC910B4694D008CDB57 /* SkUtils_opts_none.cpp in Sources */,
005B11BF12EFDC2D00A08864 /* SkFontHost_mac_coretext.cpp in Sources */,
+ 00AB17D2136EE742004E1B73 /* SkTypefaceCache.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -228,7 +232,7 @@
HEADER_SEARCH_PATHS = "/opt/local/include/**";
PREBINDING = NO;
SDKROOT = "";
- USER_HEADER_SEARCH_PATHS = "../../include//**";
+ USER_HEADER_SEARCH_PATHS = "../../src/core ../../include//**";
};
name = Debug;
};
@@ -248,7 +252,7 @@
HEADER_SEARCH_PATHS = "/opt/local/include/**";
PREBINDING = NO;
SDKROOT = "";
- USER_HEADER_SEARCH_PATHS = "../../include//**";
+ USER_HEADER_SEARCH_PATHS = "../../src/core ../../include//**";
};
name = Release;
};