aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar herb <herb@google.com>2015-11-24 08:37:01 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-11-24 08:37:02 -0800
commitbda26436faacf21ae2afd572aacd45eaa79fd0a6 (patch)
tree14bc1baac2fa0fa303857193c9484bc51de46220
parentff55b49c297251f6cc3a0f8b2ca059833629ae17 (diff)
Change XPS to use find and place glyph.
Testing: The testing I did is non-standard. I just compared images using XPS viewer. They all looked the same, but the XPS device is suffering from bit rot. BUG=skia: Review URL: https://codereview.chromium.org/1471043002
-rw-r--r--src/device/xps/SkXPSDevice.cpp191
1 files changed, 100 insertions, 91 deletions
diff --git a/src/device/xps/SkXPSDevice.cpp b/src/device/xps/SkXPSDevice.cpp
index 43c5c6cee6..f9715985e0 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,