Index: src/core/SkTextBlob.cpp |
diff --git a/src/core/SkTextBlob.cpp b/src/core/SkTextBlob.cpp |
index 3ffc41e9ba6677b5eb1904da834a4281b26800f4..3d396deba5cb4ce8fe84daeff52b64e369ddb0f4 100644 |
--- a/src/core/SkTextBlob.cpp |
+++ b/src/core/SkTextBlob.cpp |
@@ -11,6 +11,84 @@ |
#include "SkTypeface.h" |
#include "SkWriteBuffer.h" |
+namespace { |
+ |
+// TODO(fmalita): replace with SkFont. |
+class RunFont : SkNoncopyable { |
+public: |
+ RunFont(const SkPaint& paint) |
+ : fSize(paint.getTextSize()) |
+ , fScaleX(paint.getTextScaleX()) |
+ , fTypeface(SkSafeRef(paint.getTypeface())) |
+ , fSkewX(paint.getTextSkewX()) |
+ , fHinting(paint.getHinting()) |
+ , fFlags(paint.getFlags() & kFlagsMask) { } |
+ |
+ void applyToPaint(SkPaint* paint) const { |
+ paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); |
+ paint->setTypeface(fTypeface.get()); |
+ paint->setTextSize(fSize); |
+ paint->setTextScaleX(fScaleX); |
+ paint->setTextSkewX(fSkewX); |
+ paint->setHinting(static_cast<SkPaint::Hinting>(fHinting)); |
+ |
+ paint->setFlags((paint->getFlags() & ~kFlagsMask) | fFlags); |
+ } |
+ |
+ bool operator==(const RunFont& other) const { |
+ return fTypeface == other.fTypeface |
+ && fSize == other.fSize |
+ && fScaleX == other.fScaleX |
+ && fSkewX == other.fSkewX |
+ && fHinting == other.fHinting |
+ && fFlags == other.fFlags; |
+ } |
+ |
+ bool operator!=(const RunFont& other) const { |
+ return !(*this == other); |
+ } |
+private: |
+ const static uint32_t kFlagsMask = |
+ SkPaint::kAntiAlias_Flag | |
+ SkPaint::kUnderlineText_Flag | |
+ SkPaint::kStrikeThruText_Flag | |
+ SkPaint::kFakeBoldText_Flag | |
+ SkPaint::kLinearText_Flag | |
+ SkPaint::kSubpixelText_Flag | |
+ SkPaint::kDevKernText_Flag | |
+ SkPaint::kLCDRenderText_Flag | |
+ SkPaint::kEmbeddedBitmapText_Flag | |
+ SkPaint::kAutoHinting_Flag | |
+ SkPaint::kVerticalText_Flag | |
+ SkPaint::kGenA8FromLCD_Flag | |
+ SkPaint::kDistanceFieldTextTEMP_Flag; |
+ |
+ SkScalar fSize; |
+ SkScalar fScaleX; |
+ |
+ // Keep this SkAutoTUnref off the first position, to avoid interfering with SkNoncopyable |
+ // empty baseclass optimization (http://code.google.com/p/skia/issues/detail?id=3694). |
+ SkAutoTUnref<SkTypeface> fTypeface; |
+ SkScalar fSkewX; |
+ |
+ SK_COMPILE_ASSERT(SkPaint::kFull_Hinting < 4, insufficient_hinting_bits); |
+ uint32_t fHinting : 2; |
+ SK_COMPILE_ASSERT((kFlagsMask & 0xffff) == kFlagsMask, insufficient_flags_bits); |
+ uint32_t fFlags : 16; |
+ |
+ typedef SkNoncopyable INHERITED; |
+}; |
+ |
+struct RunFontStorageEquivalent { |
+ SkScalar fSize, fScaleX; |
+ void* fTypeface; |
+ SkScalar fSkewX; |
+ uint32_t fFlags; |
+}; |
+SK_COMPILE_ASSERT(sizeof(RunFont) == sizeof(RunFontStorageEquivalent), runfont_should_stay_packed); |
+ |
+} // anonymous namespace |
+ |
// |
// Textblob data is laid out into externally-managed storage as follows: |
// |
@@ -26,9 +104,9 @@ SkDEBUGCODE(static const unsigned kRunRecordMagic = 0xb10bcafe;) |
class SkTextBlob::RunRecord { |
public: |
RunRecord(uint32_t count, const SkPoint& offset, const SkPaint& font, GlyphPositioning pos) |
- : fCount(count) |
+ : fFont(font) |
+ , fCount(count) |
, fOffset(offset) |
- , fFont(font) |
, fPositioning(pos) { |
SkDEBUGCODE(fMagic = kRunRecordMagic); |
} |
@@ -41,7 +119,7 @@ public: |
return fOffset; |
} |
- const SkPaint& font() const { |
+ const RunFont& font() const { |
return fFont; |
} |
@@ -100,9 +178,9 @@ private: |
memmove(posBuffer(), initialPosBuffer, copySize); |
} |
+ RunFont fFont; |
uint32_t fCount; |
SkPoint fOffset; |
- SkPaint fFont; |
GlyphPositioning fPositioning; |
SkDEBUGCODE(unsigned fMagic;) |
@@ -262,29 +340,7 @@ SkTextBlob::GlyphPositioning SkTextBlob::RunIterator::positioning() const { |
void SkTextBlob::RunIterator::applyFontToPaint(SkPaint* paint) const { |
SkASSERT(!this->done()); |
- const SkPaint& font = fCurrentRun->font(); |
- |
- paint->setTypeface(font.getTypeface()); |
- paint->setTextEncoding(font.getTextEncoding()); |
- paint->setTextSize(font.getTextSize()); |
- paint->setTextScaleX(font.getTextScaleX()); |
- paint->setTextSkewX(font.getTextSkewX()); |
- paint->setHinting(font.getHinting()); |
- |
- uint32_t flagsMask = SkPaint::kAntiAlias_Flag |
- | SkPaint::kUnderlineText_Flag |
- | SkPaint::kStrikeThruText_Flag |
- | SkPaint::kFakeBoldText_Flag |
- | SkPaint::kLinearText_Flag |
- | SkPaint::kSubpixelText_Flag |
- | SkPaint::kDevKernText_Flag |
- | SkPaint::kLCDRenderText_Flag |
- | SkPaint::kEmbeddedBitmapText_Flag |
- | SkPaint::kAutoHinting_Flag |
- | SkPaint::kVerticalText_Flag |
- | SkPaint::kGenA8FromLCD_Flag |
- | SkPaint::kDistanceFieldTextTEMP_Flag; |
- paint->setFlags((paint->getFlags() & ~flagsMask) | (font.getFlags() & flagsMask)); |
+ fCurrentRun->font().applyToPaint(paint); |
} |
SkTextBlobBuilder::SkTextBlobBuilder() |
@@ -308,7 +364,9 @@ SkRect SkTextBlobBuilder::TightRunBounds(const SkTextBlob::RunRecord& run) { |
SkASSERT(SkTextBlob::kDefault_Positioning == run.positioning()); |
SkRect bounds; |
- run.font().measureText(run.glyphBuffer(), run.glyphCount() * sizeof(uint16_t), &bounds); |
+ SkPaint paint; |
+ run.font().applyToPaint(&paint); |
+ paint.measureText(run.glyphBuffer(), run.glyphCount() * sizeof(uint16_t), &bounds); |
return bounds.makeOffset(run.offset().x(), run.offset().y()); |
} |
@@ -346,7 +404,9 @@ SkRect SkTextBlobBuilder::ConservativeRunBounds(const SkTextBlob::RunRecord& run |
} |
// Expand by typeface glyph bounds. |
- const SkRect fontBounds = run.font().getFontBounds(); |
+ SkPaint paint; |
+ run.font().applyToPaint(&paint); |
+ const SkRect fontBounds = paint.getFontBounds(); |
bounds.fLeft += fontBounds.left(); |
bounds.fTop += fontBounds.top(); |
bounds.fRight += fontBounds.right(); |
@@ -366,7 +426,6 @@ void SkTextBlobBuilder::updateDeferredBounds() { |
SkASSERT(fLastRun >= sizeof(SkTextBlob)); |
SkTextBlob::RunRecord* run = reinterpret_cast<SkTextBlob::RunRecord*>(fStorage.get() + |
fLastRun); |
- SkASSERT(SkPaint::kGlyphID_TextEncoding == run->font().getTextEncoding()); |
// FIXME: we should also use conservative bounds for kDefault_Positioning. |
SkRect runBounds = SkTextBlob::kDefault_Positioning == run->positioning() ? |