Chromium Code Reviews| Index: src/device/xps/SkXPSDevice.cpp |
| diff --git a/src/device/xps/SkXPSDevice.cpp b/src/device/xps/SkXPSDevice.cpp |
| index 43c5c6cee63b6a2d5cf16632c2c53ec92a96e3fb..aa84d8cd9c278bf5763071c7a74cae89257a109d 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 size_t 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, |
| @@ -2137,35 +2126,44 @@ void SkXPSDevice::drawText(const SkDraw& d, |
| //TODO: add automation "text" |
| return; |
| } |
| - |
| + |
|
bungeman-skia
2015/11/23 20:10:34
nit: whitepace
herb_g
2015/11/24 15:34:44
Done.
|
| 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). |
|
bungeman-skia
2015/11/23 20:10:34
nit: line length, something like
// Advance w
herb_g
2015/11/24 15:34:44
Done.
|
| + FLOAT centemPerUnit = 100.0f / SkScalarToFLOAT(paint.getTextSize()); |
| + GlyphRun xpsGlyphs; |
| + xpsGlyphs.setReserve(num_glyph_guess(paint.getTextEncoding(), static_cast<const char*>(text), byteLen)); |
|
bungeman-skia
2015/11/23 20:10:34
nit: line length
herb_g
2015/11/24 15:34:45
Done.
|
| + |
| + ProcessOneGlyph processOneGlyph(centemPerUnit, typeface->glyphsUsed, &xpsGlyphs); |
| - myDraw.drawText(static_cast<const char*>(text), byteLen, x, y, paint); |
| + SkFindAndPlaceGlyph::ProcessText( |
| + paint.getTextEncoding(), static_cast<const char*>(text), byteLen, |
| + SkPoint{ x, y }, matrix, paint.getTextAlign(), cache, processOneGlyph); |
| // SkDraw may have clipped out the glyphs, so we need to check |
|
bungeman-skia
2015/11/23 20:10:34
No longer using SkDraw for this, so this comment i
herb_g
2015/11/24 15:34:44
Done.
|
| - 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, |
| @@ -2191,31 +2189,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); |
| + |
| + SkFindAndPlaceGlyph::ProcessPosText( |
| + paint.getTextEncoding(), static_cast<const char*>(text), byteLen, |
| + offset, matrix, pos, scalarsPerPos, paint.getTextAlign(), cache, processOneGlyph); |
| - myDraw.drawPosText(static_cast<const char*>(text), byteLen, pos, scalarsPerPos, offset, paint); |
| // 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, |