Index: src/device/xps/SkXPSDevice.cpp |
diff --git a/src/device/xps/SkXPSDevice.cpp b/src/device/xps/SkXPSDevice.cpp |
index 43c5c6cee63b6a2d5cf16632c2c53ec92a96e3fb..f9715985e0a84cc520f5771eae4287f5d6daa662 100644 |
--- a/src/device/xps/SkXPSDevice.cpp |
+++ b/src/device/xps/SkXPSDevice.cpp |
@@ -25,6 +25,7 @@ |
#include "SkDraw.h" |
#include "SkDrawProcs.h" |
#include "SkEndian.h" |
+#include "SkFindAndPlaceGlyph.h" |
#include "SkGeometry.h" |
#include "SkGlyphCache.h" |
#include "SkHRESULT.h" |
@@ -2044,74 +2045,18 @@ HRESULT SkXPSDevice::AddGlyphs(const SkDraw& d, |
return S_OK; |
} |
-struct SkXPSDrawProcs : public SkDrawProcs { |
-public: |
- /** [in] Advance width and offsets for glyphs measured in |
- hundredths of the font em size (XPS Spec 5.1.3). */ |
- FLOAT centemPerUnit; |
- /** [in,out] The accumulated glyphs used in the current typeface. */ |
- SkBitSet* glyphUse; |
- /** [out] The glyphs to draw. */ |
- SkTDArray<XPS_GLYPH_INDEX> xpsGlyphs; |
-}; |
- |
-static void xps_draw_1_glyph(const SkDraw1Glyph& state, |
- Sk48Dot16 fx, Sk48Dot16 fy, |
- const SkGlyph& skGlyph) { |
- SkASSERT(skGlyph.fWidth > 0 && skGlyph.fHeight > 0); |
- |
- SkXPSDrawProcs* procs = static_cast<SkXPSDrawProcs*>(state.fDraw->fProcs); |
- |
- //Draw pre-adds half the sampling frequency for floor rounding. |
- SkScalar x = Sk48Dot16ToScalar(fx) - state.fHalfSampleX; |
- SkScalar y = Sk48Dot16ToScalar(fy) - state.fHalfSampleY; |
- |
- XPS_GLYPH_INDEX* xpsGlyph = procs->xpsGlyphs.append(); |
- uint16_t glyphID = skGlyph.getGlyphID(); |
- procs->glyphUse->setBit(glyphID, true); |
- xpsGlyph->index = glyphID; |
- if (1 == procs->xpsGlyphs.count()) { |
- xpsGlyph->advanceWidth = 0.0f; |
- xpsGlyph->horizontalOffset = SkScalarToFloat(x) * procs->centemPerUnit; |
- xpsGlyph->verticalOffset = SkScalarToFloat(y) * -procs->centemPerUnit; |
- } else { |
- const XPS_GLYPH_INDEX& first = procs->xpsGlyphs[0]; |
- xpsGlyph->advanceWidth = 0.0f; |
- xpsGlyph->horizontalOffset = (SkScalarToFloat(x) * procs->centemPerUnit) |
- - first.horizontalOffset; |
- xpsGlyph->verticalOffset = (SkScalarToFloat(y) * -procs->centemPerUnit) |
- - first.verticalOffset; |
- } |
-} |
- |
-static void text_draw_init(const SkPaint& paint, |
- const void* text, size_t byteLength, |
- SkBitSet& glyphsUsed, |
- SkDraw& myDraw, SkXPSDrawProcs& procs) { |
- procs.fD1GProc = xps_draw_1_glyph; |
- int numGlyphGuess; |
- switch (paint.getTextEncoding()) { |
- case SkPaint::kUTF8_TextEncoding: |
- numGlyphGuess = SkUTF8_CountUnichars( |
- static_cast<const char *>(text), |
- byteLength); |
- break; |
- case SkPaint::kUTF16_TextEncoding: |
- numGlyphGuess = SkUTF16_CountUnichars( |
- static_cast<const uint16_t *>(text), |
- SkToInt(byteLength)); |
- break; |
- case SkPaint::kGlyphID_TextEncoding: |
- numGlyphGuess = SkToInt(byteLength / 2); |
- break; |
- default: |
- SK_ALWAYSBREAK(true); |
+static int num_glyph_guess(SkPaint::TextEncoding encoding, const void* text, size_t byteLength) { |
+ switch (encoding) { |
+ case SkPaint::kUTF8_TextEncoding: |
+ return SkUTF8_CountUnichars(static_cast<const char *>(text), byteLength); |
+ case SkPaint::kUTF16_TextEncoding: |
+ return SkUTF16_CountUnichars(static_cast<const uint16_t *>(text), SkToInt(byteLength)); |
+ case SkPaint::kGlyphID_TextEncoding: |
+ return SkToInt(byteLength / 2); |
+ default: |
+ SK_ALWAYSBREAK(true); |
} |
- procs.xpsGlyphs.setReserve(numGlyphGuess); |
- procs.glyphUse = &glyphsUsed; |
- procs.centemPerUnit = 100.0f / SkScalarToFLOAT(paint.getTextSize()); |
- |
- myDraw.fProcs = &procs; |
+ return 0; |
} |
static bool text_must_be_pathed(const SkPaint& paint, const SkMatrix& matrix) { |
@@ -2124,6 +2069,50 @@ static bool text_must_be_pathed(const SkPaint& paint, const SkMatrix& matrix) { |
; |
} |
+typedef SkTDArray<XPS_GLYPH_INDEX> GlyphRun; |
+ |
+class ProcessOneGlyph { |
+public: |
+ ProcessOneGlyph(FLOAT centemPerUnit, SkBitSet* glyphUse, GlyphRun* xpsGlyphs) |
+ : fCentemPerUnit(centemPerUnit) |
+ , fGlyphUse(glyphUse) |
+ , fXpsGlyphs(xpsGlyphs) { } |
+ |
+ void operator()(const SkGlyph& glyph, SkPoint position, SkPoint) { |
+ SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); |
+ |
+ SkScalar x = position.fX; |
+ SkScalar y = position.fY; |
+ |
+ XPS_GLYPH_INDEX* xpsGlyph = fXpsGlyphs->append(); |
+ uint16_t glyphID = glyph.getGlyphID(); |
+ fGlyphUse->setBit(glyphID, true); |
+ xpsGlyph->index = glyphID; |
+ if (1 == fXpsGlyphs->count()) { |
+ xpsGlyph->advanceWidth = 0.0f; |
+ xpsGlyph->horizontalOffset = SkScalarToFloat(x) * fCentemPerUnit; |
+ xpsGlyph->verticalOffset = SkScalarToFloat(y) * -fCentemPerUnit; |
+ } |
+ else { |
+ const XPS_GLYPH_INDEX& first = (*fXpsGlyphs)[0]; |
+ xpsGlyph->advanceWidth = 0.0f; |
+ xpsGlyph->horizontalOffset = (SkScalarToFloat(x) * fCentemPerUnit) |
+ - first.horizontalOffset; |
+ xpsGlyph->verticalOffset = (SkScalarToFloat(y) * -fCentemPerUnit) |
+ - first.verticalOffset; |
+ } |
+ } |
+ |
+private: |
+ /** [in] Advance width and offsets for glyphs measured in |
+ hundredths of the font em size (XPS Spec 5.1.3). */ |
+ const FLOAT fCentemPerUnit; |
+ /** [in,out] The accumulated glyphs used in the current typeface. */ |
+ SkBitSet* const fGlyphUse; |
+ /** [out] The glyphs to draw. */ |
+ GlyphRun* const fXpsGlyphs; |
+}; |
+ |
void SkXPSDevice::drawText(const SkDraw& d, |
const void* text, size_t byteLen, |
SkScalar x, SkScalar y, |
@@ -2141,31 +2130,41 @@ void SkXPSDevice::drawText(const SkDraw& d, |
TypefaceUse* typeface; |
HRV(CreateTypefaceUse(paint, &typeface)); |
- SkDraw myDraw(d); |
- myDraw.fMatrix = &SkMatrix::I(); |
- SkXPSDrawProcs procs; |
- text_draw_init(paint, text, byteLen, *typeface->glyphsUsed, myDraw, procs); |
+ const SkMatrix& matrix = SkMatrix::I(); |
+ |
+ SkAutoGlyphCache autoCache(paint, &this->surfaceProps(), &matrix); |
+ SkGlyphCache* cache = autoCache.getCache(); |
+ |
+ // Advance width and offsets for glyphs measured in hundredths of the font em size |
+ // (XPS Spec 5.1.3). |
+ FLOAT centemPerUnit = 100.0f / SkScalarToFLOAT(paint.getTextSize()); |
+ GlyphRun xpsGlyphs; |
+ xpsGlyphs.setReserve(num_glyph_guess(paint.getTextEncoding(), |
+ static_cast<const char*>(text), byteLen)); |
- myDraw.drawText(static_cast<const char*>(text), byteLen, x, y, paint); |
+ ProcessOneGlyph processOneGlyph(centemPerUnit, typeface->glyphsUsed, &xpsGlyphs); |
- // SkDraw may have clipped out the glyphs, so we need to check |
- if (procs.xpsGlyphs.count() == 0) { |
+ SkFindAndPlaceGlyph::ProcessText( |
+ paint.getTextEncoding(), static_cast<const char*>(text), byteLen, |
+ SkPoint{ x, y }, matrix, paint.getTextAlign(), cache, processOneGlyph); |
+ |
+ if (xpsGlyphs.count() == 0) { |
return; |
} |
XPS_POINT origin = { |
- procs.xpsGlyphs[0].horizontalOffset / procs.centemPerUnit, |
- procs.xpsGlyphs[0].verticalOffset / -procs.centemPerUnit, |
+ xpsGlyphs[0].horizontalOffset / centemPerUnit, |
+ xpsGlyphs[0].verticalOffset / -centemPerUnit, |
}; |
- procs.xpsGlyphs[0].horizontalOffset = 0.0f; |
- procs.xpsGlyphs[0].verticalOffset = 0.0f; |
+ xpsGlyphs[0].horizontalOffset = 0.0f; |
+ xpsGlyphs[0].verticalOffset = 0.0f; |
HRV(AddGlyphs(d, |
this->fXpsFactory.get(), |
this->fCurrentXpsCanvas.get(), |
typeface, |
nullptr, |
- procs.xpsGlyphs.begin(), procs.xpsGlyphs.count(), |
+ xpsGlyphs.begin(), xpsGlyphs.count(), |
&origin, |
SkScalarToFLOAT(paint.getTextSize()), |
XPS_STYLE_SIMULATION_NONE, |
@@ -2191,31 +2190,41 @@ void SkXPSDevice::drawPosText(const SkDraw& d, |
TypefaceUse* typeface; |
HRV(CreateTypefaceUse(paint, &typeface)); |
- SkDraw myDraw(d); |
- myDraw.fMatrix = &SkMatrix::I(); |
- SkXPSDrawProcs procs; |
- text_draw_init(paint, text, byteLen, *typeface->glyphsUsed, myDraw, procs); |
+ const SkMatrix& matrix = SkMatrix::I(); |
+ |
+ SkAutoGlyphCache autoCache(paint, &this->surfaceProps(), &matrix); |
+ SkGlyphCache* cache = autoCache.getCache(); |
+ |
+ // Advance width and offsets for glyphs measured in hundredths of the font em size |
+ // (XPS Spec 5.1.3). |
+ FLOAT centemPerUnit = 100.0f / SkScalarToFLOAT(paint.getTextSize()); |
+ GlyphRun xpsGlyphs; |
+ xpsGlyphs.setReserve(num_glyph_guess(paint.getTextEncoding(), |
+ static_cast<const char*>(text), byteLen)); |
+ |
+ ProcessOneGlyph processOneGlyph(centemPerUnit, typeface->glyphsUsed, &xpsGlyphs); |
- myDraw.drawPosText(static_cast<const char*>(text), byteLen, pos, scalarsPerPos, offset, paint); |
+ SkFindAndPlaceGlyph::ProcessPosText( |
+ paint.getTextEncoding(), static_cast<const char*>(text), byteLen, |
+ offset, matrix, pos, scalarsPerPos, paint.getTextAlign(), cache, processOneGlyph); |
- // SkDraw may have clipped out the glyphs, so we need to check |
- if (procs.xpsGlyphs.count() == 0) { |
+ if (xpsGlyphs.count() == 0) { |
return; |
} |
XPS_POINT origin = { |
- procs.xpsGlyphs[0].horizontalOffset / procs.centemPerUnit, |
- procs.xpsGlyphs[0].verticalOffset / -procs.centemPerUnit, |
+ xpsGlyphs[0].horizontalOffset / centemPerUnit, |
+ xpsGlyphs[0].verticalOffset / -centemPerUnit, |
}; |
- procs.xpsGlyphs[0].horizontalOffset = 0.0f; |
- procs.xpsGlyphs[0].verticalOffset = 0.0f; |
+ xpsGlyphs[0].horizontalOffset = 0.0f; |
+ xpsGlyphs[0].verticalOffset = 0.0f; |
HRV(AddGlyphs(d, |
this->fXpsFactory.get(), |
this->fCurrentXpsCanvas.get(), |
typeface, |
nullptr, |
- procs.xpsGlyphs.begin(), procs.xpsGlyphs.count(), |
+ xpsGlyphs.begin(), xpsGlyphs.count(), |
&origin, |
SkScalarToFLOAT(paint.getTextSize()), |
XPS_STYLE_SIMULATION_NONE, |