have paint's measure calls respect vertical
git-svn-id: http://skia.googlecode.com/svn/trunk@2660 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
4e27d6e000
commit
44da42e92f
@ -149,6 +149,7 @@ private:
|
||||
const SkPath* fPath; // returned in next
|
||||
SkScalar fXPos; // accumulated xpos, returned in next
|
||||
SkAutoKern fAutoKern;
|
||||
int fXYIndex; // cache for horizontal -vs- vertical text
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -762,23 +762,29 @@ public:
|
||||
return this->textToGlyphs(text, byteLength, NULL);
|
||||
}
|
||||
|
||||
/** Return the width of the text.
|
||||
@param text The text to be measured
|
||||
@param length Number of bytes of text to measure
|
||||
@param bounds If not NULL, returns the bounds of the text,
|
||||
relative to (0, 0).
|
||||
@param scale If not 0, return width as if the canvas were scaled
|
||||
by this value
|
||||
@return The advance width of the text
|
||||
*/
|
||||
/** Return the width of the text. This will return the vertical measure
|
||||
* if isVerticalText() is true, in which case the returned value should
|
||||
* be treated has a height instead of a width.
|
||||
*
|
||||
* @param text The text to be measured
|
||||
* @param length Number of bytes of text to measure
|
||||
* @param bounds If not NULL, returns the bounds of the text,
|
||||
* relative to (0, 0).
|
||||
* @param scale If not 0, return width as if the canvas were scaled
|
||||
* by this value
|
||||
* @return The advance width of the text
|
||||
*/
|
||||
SkScalar measureText(const void* text, size_t length,
|
||||
SkRect* bounds, SkScalar scale = 0) const;
|
||||
|
||||
/** Return the width of the text.
|
||||
@param text Address of the text
|
||||
@param length Number of bytes of text to measure
|
||||
@return The width of the text
|
||||
*/
|
||||
/** Return the width of the text. This will return the vertical measure
|
||||
* if isVerticalText() is true, in which case the returned value should
|
||||
* be treated has a height instead of a width.
|
||||
*
|
||||
* @param text Address of the text
|
||||
* @param length Number of bytes of text to measure
|
||||
* @return The width of the text
|
||||
*/
|
||||
SkScalar measureText(const void* text, size_t length) const {
|
||||
return this->measureText(text, length, NULL, 0);
|
||||
}
|
||||
@ -796,33 +802,38 @@ public:
|
||||
kBackward_TextBufferDirection
|
||||
};
|
||||
|
||||
/** Return the width of the text.
|
||||
@param text The text to be measured
|
||||
@param length Number of bytes of text to measure
|
||||
@param maxWidth Maximum width. Only the subset of text whose accumulated
|
||||
widths are <= maxWidth are measured.
|
||||
@param measuredWidth Optional. If non-null, this returns the actual
|
||||
width of the measured text.
|
||||
@param tbd Optional. The direction the text buffer should be
|
||||
traversed during measuring.
|
||||
@return The number of bytes of text that were measured. Will be
|
||||
<= length.
|
||||
*/
|
||||
/** Return the number of bytes of text that were measured. If
|
||||
* isVerticalText() is true, then the vertical advances are used for
|
||||
* the measurement.
|
||||
*
|
||||
* @param text The text to be measured
|
||||
* @param length Number of bytes of text to measure
|
||||
* @param maxWidth Maximum width. Only the subset of text whose accumulated
|
||||
* widths are <= maxWidth are measured.
|
||||
* @param measuredWidth Optional. If non-null, this returns the actual
|
||||
* width of the measured text.
|
||||
* @param tbd Optional. The direction the text buffer should be
|
||||
* traversed during measuring.
|
||||
* @return The number of bytes of text that were measured. Will be
|
||||
* <= length.
|
||||
*/
|
||||
size_t breakText(const void* text, size_t length, SkScalar maxWidth,
|
||||
SkScalar* measuredWidth = NULL,
|
||||
TextBufferDirection tbd = kForward_TextBufferDirection)
|
||||
const;
|
||||
|
||||
/** Return the advance widths for the characters in the string.
|
||||
@param text the text
|
||||
@param byteLength number of bytes to of text
|
||||
@param widths If not null, returns the array of advance widths of
|
||||
the glyphs. If not NULL, must be at least a large
|
||||
as the number of unichars in the specified text.
|
||||
@param bounds If not null, returns the bounds for each of
|
||||
character, relative to (0, 0)
|
||||
@return the number of unichars in the specified text.
|
||||
*/
|
||||
/** Return the advances for the text. These will be vertical advances if
|
||||
* isVerticalText() returns true.
|
||||
*
|
||||
* @param text the text
|
||||
* @param byteLength number of bytes to of text
|
||||
* @param widths If not null, returns the array of advances for
|
||||
* the glyphs. If not NULL, must be at least a large
|
||||
* as the number of unichars in the specified text.
|
||||
* @param bounds If not null, returns the bounds for each of
|
||||
* character, relative to (0, 0)
|
||||
* @return the number of unichars in the specified text.
|
||||
*/
|
||||
int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
|
||||
SkRect bounds[] = NULL) const;
|
||||
|
||||
|
@ -801,7 +801,7 @@ typedef int64_t Sk48Dot16;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void join_bounds(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
|
||||
static void join_bounds_x(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
|
||||
SkScalar sx = Sk48Dot16ToScalar(dx);
|
||||
bounds->join(SkIntToScalar(g.fLeft) + sx,
|
||||
SkIntToScalar(g.fTop),
|
||||
@ -809,6 +809,22 @@ static void join_bounds(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
|
||||
SkIntToScalar(g.fTop + g.fHeight));
|
||||
}
|
||||
|
||||
static void join_bounds_y(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dy) {
|
||||
SkScalar sy = Sk48Dot16ToScalar(dy);
|
||||
bounds->join(SkIntToScalar(g.fLeft),
|
||||
SkIntToScalar(g.fTop) + sy,
|
||||
SkIntToScalar(g.fLeft + g.fWidth),
|
||||
SkIntToScalar(g.fTop + g.fHeight) + sy);
|
||||
}
|
||||
|
||||
typedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, Sk48Dot16);
|
||||
|
||||
// xyIndex is 0 for fAdvanceX or 1 for fAdvanceY
|
||||
static SkFixed advance(const SkGlyph& glyph, int xyIndex) {
|
||||
SkASSERT(0 == xyIndex || 1 == xyIndex);
|
||||
return (&glyph.fAdvanceX)[xyIndex];
|
||||
}
|
||||
|
||||
SkScalar SkPaint::measure_text(SkGlyphCache* cache,
|
||||
const char* text, size_t byteLength,
|
||||
int* count, SkRect* bounds) const {
|
||||
@ -825,13 +841,23 @@ SkScalar SkPaint::measure_text(SkGlyphCache* cache,
|
||||
glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
|
||||
NULL != bounds);
|
||||
|
||||
int xyIndex;
|
||||
JoinBoundsProc joinBoundsProc;
|
||||
if (this->isVerticalText()) {
|
||||
xyIndex = 1;
|
||||
joinBoundsProc = join_bounds_y;
|
||||
} else {
|
||||
xyIndex = 0;
|
||||
joinBoundsProc = join_bounds_x;
|
||||
}
|
||||
|
||||
int n = 1;
|
||||
const char* stop = (const char*)text + byteLength;
|
||||
const SkGlyph* g = &glyphCacheProc(cache, &text);
|
||||
// our accumulated fixed-point advances might overflow 16.16, so we use
|
||||
// a 48.16 (64bit) accumulator, and then convert that to scalar at the
|
||||
// very end.
|
||||
Sk48Dot16 x = g->fAdvanceX;
|
||||
Sk48Dot16 x = advance(*g, xyIndex);
|
||||
|
||||
SkAutoKern autokern;
|
||||
|
||||
@ -841,11 +867,11 @@ SkScalar SkPaint::measure_text(SkGlyphCache* cache,
|
||||
for (; text < stop; n++) {
|
||||
rsb = g->fRsbDelta;
|
||||
g = &glyphCacheProc(cache, &text);
|
||||
x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + g->fAdvanceX;
|
||||
x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + advance(*g, xyIndex);
|
||||
}
|
||||
} else {
|
||||
for (; text < stop; n++) {
|
||||
x += glyphCacheProc(cache, &text).fAdvanceX;
|
||||
x += advance(glyphCacheProc(cache, &text), xyIndex);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -856,14 +882,14 @@ SkScalar SkPaint::measure_text(SkGlyphCache* cache,
|
||||
rsb = g->fRsbDelta;
|
||||
g = &glyphCacheProc(cache, &text);
|
||||
x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
|
||||
join_bounds(*g, bounds, x);
|
||||
x += g->fAdvanceX;
|
||||
joinBoundsProc(*g, bounds, x);
|
||||
x += advance(*g, xyIndex);
|
||||
}
|
||||
} else {
|
||||
for (; text < stop; n++) {
|
||||
g = &glyphCacheProc(cache, &text);
|
||||
join_bounds(*g, bounds, x);
|
||||
x += g->fAdvanceX;
|
||||
joinBoundsProc(*g, bounds, x);
|
||||
x += advance(*g, xyIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -968,6 +994,7 @@ size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
|
||||
SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false);
|
||||
const char* stop;
|
||||
SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
|
||||
const int xyIndex = this->isVerticalText() ? 1 : 0;
|
||||
// use 64bits for our accumulator, to avoid overflowing 16.16
|
||||
Sk48Dot16 max = SkScalarToFixed(maxWidth);
|
||||
Sk48Dot16 width = 0;
|
||||
@ -979,7 +1006,7 @@ size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
|
||||
while (pred(text, stop)) {
|
||||
const char* curr = text;
|
||||
const SkGlyph& g = glyphCacheProc(cache, &text);
|
||||
SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + g.fAdvanceX;
|
||||
SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + advance(g, xyIndex);
|
||||
if ((width += x) > max) {
|
||||
width -= x;
|
||||
text = curr;
|
||||
@ -990,7 +1017,7 @@ size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
|
||||
} else {
|
||||
while (pred(text, stop)) {
|
||||
const char* curr = text;
|
||||
SkFixed x = glyphCacheProc(cache, &text).fAdvanceX;
|
||||
SkFixed x = advance(glyphCacheProc(cache, &text), xyIndex);
|
||||
if ((width += x) > max) {
|
||||
width -= x;
|
||||
text = curr;
|
||||
@ -1100,6 +1127,7 @@ int SkPaint::getTextWidths(const void* textData, size_t byteLength,
|
||||
const char* text = (const char*)textData;
|
||||
const char* stop = text + byteLength;
|
||||
int count = 0;
|
||||
const int xyIndex = this->isVerticalText() ? 1 : 0;
|
||||
|
||||
if (this->isDevKernText()) {
|
||||
// we adjust the widths returned here through auto-kerning
|
||||
@ -1116,7 +1144,7 @@ int SkPaint::getTextWidths(const void* textData, size_t byteLength,
|
||||
SkScalar w = SkFixedToScalar(prevWidth + adjust);
|
||||
*widths++ = SkScalarMul(w, scale);
|
||||
}
|
||||
prevWidth = g.fAdvanceX;
|
||||
prevWidth = advance(g, xyIndex);
|
||||
}
|
||||
if (bounds) {
|
||||
set_bounds(g, bounds++, scale);
|
||||
@ -1135,7 +1163,7 @@ int SkPaint::getTextWidths(const void* textData, size_t byteLength,
|
||||
if (count > 0) {
|
||||
*widths++ = SkFixedToScalar(prevWidth + adjust);
|
||||
}
|
||||
prevWidth = g.fAdvanceX;
|
||||
prevWidth = advance(g, xyIndex);
|
||||
}
|
||||
if (bounds) {
|
||||
set_bounds(g, bounds++);
|
||||
@ -1151,7 +1179,7 @@ int SkPaint::getTextWidths(const void* textData, size_t byteLength,
|
||||
while (text < stop) {
|
||||
const SkGlyph& g = glyphCacheProc(cache, &text);
|
||||
if (widths) {
|
||||
*widths++ = SkScalarMul(SkFixedToScalar(g.fAdvanceX),
|
||||
*widths++ = SkScalarMul(SkFixedToScalar(advance(g, xyIndex)),
|
||||
scale);
|
||||
}
|
||||
if (bounds) {
|
||||
@ -1163,7 +1191,7 @@ int SkPaint::getTextWidths(const void* textData, size_t byteLength,
|
||||
while (text < stop) {
|
||||
const SkGlyph& g = glyphCacheProc(cache, &text);
|
||||
if (widths) {
|
||||
*widths++ = SkFixedToScalar(g.fAdvanceX);
|
||||
*widths++ = SkFixedToScalar(advance(g, xyIndex));
|
||||
}
|
||||
if (bounds) {
|
||||
set_bounds(g, bounds++);
|
||||
@ -1845,6 +1873,8 @@ SkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
|
||||
|
||||
fText = text;
|
||||
fStop = text + length;
|
||||
|
||||
fXYIndex = paint.isVerticalText() ? 1 : 0;
|
||||
}
|
||||
|
||||
SkTextToPathIter::~SkTextToPathIter() {
|
||||
@ -1856,7 +1886,7 @@ const SkPath* SkTextToPathIter::next(SkScalar* xpos) {
|
||||
const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
|
||||
|
||||
fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
|
||||
fPrevAdvance = glyph.fAdvanceX; // + fPaint.getTextTracking();
|
||||
fPrevAdvance = advance(glyph, fXYIndex); // + fPaint.getTextTracking();
|
||||
|
||||
if (glyph.fWidth) {
|
||||
if (xpos) {
|
||||
|
Loading…
Reference in New Issue
Block a user