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