提交 6292e1a9 编写于 作者: K Keisuke Kuroyanagi

Refactoring: Introduce helper class to iterate runs.

This doesn't change current behavior. It's a preparation
for the following CLs.

Bug: 22408712
Change-Id: Ic018422254aa3904655f499194caad74f0c0fc5d
上级 2a79f59e
...@@ -129,7 +129,7 @@ private: ...@@ -129,7 +129,7 @@ private:
int findFace(FakedFont face, LayoutContext* ctx); int findFace(FakedFont face, LayoutContext* ctx);
// Lay out a single bidi run // Lay out a single bidi run
void doLayoutRunCached(const uint16_t* buf, size_t start, size_t count, size_t bufSize, void doLayoutRunCached(const uint16_t* buf, size_t runStart, size_t runLength, size_t bufSize,
bool isRtl, LayoutContext* ctx, size_t dstStart); bool isRtl, LayoutContext* ctx, size_t dstStart);
// Lay out a single word // Lay out a single word
......
...@@ -488,71 +488,162 @@ static bool isScriptOkForLetterspacing(hb_script_t script) { ...@@ -488,71 +488,162 @@ static bool isScriptOkForLetterspacing(hb_script_t script) {
); );
} }
void Layout::doLayout(const uint16_t* buf, size_t start, size_t count, size_t bufSize, class BidiText {
int bidiFlags, const FontStyle &style, const MinikinPaint &paint) { public:
AutoMutex _l(gMinikinLock); class Iter {
public:
struct RunInfo {
int32_t mRunStart;
int32_t mRunLength;
bool mIsRtl;
};
LayoutContext ctx; Iter(UBiDi* bidi, size_t start, size_t end, size_t runIndex, size_t runCount, bool isRtl);
ctx.style = style;
ctx.paint = paint;
bool isRtl = (bidiFlags & kDirection_Mask) != 0; bool operator!= (const Iter& other) const {
bool doSingleRun = true; return mIsEnd != other.mIsEnd || mNextRunIndex != other.mNextRunIndex
|| mBidi != other.mBidi;
}
reset(); const RunInfo& operator* () const {
mAdvances.resize(count, 0); return mRunInfo;
}
if (!(bidiFlags == kBidi_Force_LTR || bidiFlags == kBidi_Force_RTL)) { const Iter& operator++ () {
UBiDi* bidi = ubidi_open(); updateRunInfo();
if (bidi) { return *this;
UErrorCode status = U_ZERO_ERROR;
UBiDiLevel bidiReq = bidiFlags;
if (bidiFlags == kBidi_Default_LTR) {
bidiReq = UBIDI_DEFAULT_LTR;
} else if (bidiFlags == kBidi_Default_RTL) {
bidiReq = UBIDI_DEFAULT_RTL;
} }
ubidi_setPara(bidi, buf, bufSize, bidiReq, NULL, &status);
if (U_SUCCESS(status)) { private:
int paraDir = ubidi_getParaLevel(bidi) & kDirection_Mask; UBiDi* const mBidi;
ssize_t rc = ubidi_countRuns(bidi, &status); bool mIsEnd;
if (!U_SUCCESS(status) || rc < 0) { size_t mNextRunIndex;
ALOGW("error counting bidi runs, status = %d", status); const size_t mRunCount;
const int32_t mStart;
const int32_t mEnd;
RunInfo mRunInfo;
void updateRunInfo();
};
BidiText(const uint16_t* buf, size_t start, size_t count, size_t bufSize, int bidiFlags);
~BidiText() {
if (mBidi) {
ubidi_close(mBidi);
}
}
Iter begin () const {
return Iter(mBidi, mStart, mEnd, 0, mRunCount, mIsRtl);
}
Iter end() const {
return Iter(mBidi, mStart, mEnd, mRunCount, mRunCount, mIsRtl);
}
private:
const size_t mStart;
const size_t mEnd;
const size_t mBufSize;
UBiDi* mBidi;
size_t mRunCount;
bool mIsRtl;
DISALLOW_COPY_AND_ASSIGN(BidiText);
};
BidiText::Iter::Iter(UBiDi* bidi, size_t start, size_t end, size_t runIndex, size_t runCount,
bool isRtl)
: mBidi(bidi), mIsEnd(runIndex == runCount), mNextRunIndex(runIndex), mRunCount(runCount),
mStart(start), mEnd(end), mRunInfo() {
if (mRunCount == 1) {
mRunInfo.mRunStart = start;
mRunInfo.mRunLength = end - start;
mRunInfo.mIsRtl = isRtl;
mNextRunIndex = mRunCount;
return;
}
updateRunInfo();
}
void BidiText::Iter::updateRunInfo() {
if (mNextRunIndex == mRunCount) {
// All runs have been iterated.
mIsEnd = true;
return;
} }
if (!U_SUCCESS(status) || rc <= 1) {
isRtl = (paraDir == kBidi_RTL);
} else {
doSingleRun = false;
// iterate through runs
for (ssize_t i = 0; i < (ssize_t)rc; i++) {
int32_t startRun = -1; int32_t startRun = -1;
int32_t lengthRun = -1; int32_t lengthRun = -1;
UBiDiDirection runDir = ubidi_getVisualRun(bidi, i, &startRun, &lengthRun); const UBiDiDirection runDir = ubidi_getVisualRun(mBidi, mNextRunIndex, &startRun, &lengthRun);
mNextRunIndex++;
if (startRun == -1 || lengthRun == -1) { if (startRun == -1 || lengthRun == -1) {
ALOGE("invalid visual run"); ALOGE("invalid visual run");
// skip the invalid run // skip the invalid run.
continue; updateRunInfo();
return;
} }
int32_t endRun = std::min(startRun + lengthRun, int32_t(start + count)); const int32_t runEnd = std::min(startRun + lengthRun, mEnd);
startRun = std::max(startRun, int32_t(start)); mRunInfo.mRunStart = std::max(startRun, mStart);
lengthRun = endRun - startRun; mRunInfo.mRunLength = runEnd - mRunInfo.mRunStart;
if (lengthRun > 0) { if (mRunInfo.mRunLength <= 0) {
isRtl = (runDir == UBIDI_RTL); // skip the empty run.
doLayoutRunCached(buf, startRun, lengthRun, bufSize, isRtl, &ctx, updateRunInfo();
start); return;
}
mRunInfo.mIsRtl = (runDir == UBIDI_RTL);
}
BidiText::BidiText(const uint16_t* buf, size_t start, size_t count, size_t bufSize, int bidiFlags)
: mStart(start), mEnd(start + count), mBufSize(bufSize), mBidi(NULL), mRunCount(1),
mIsRtl((bidiFlags & kDirection_Mask) != 0) {
if (bidiFlags == kBidi_Force_LTR || bidiFlags == kBidi_Force_RTL) {
// force single run.
return;
} }
mBidi = ubidi_open();
if (!mBidi) {
ALOGE("error creating bidi object");
return;
} }
UErrorCode status = U_ZERO_ERROR;
UBiDiLevel bidiReq = bidiFlags;
if (bidiFlags == kBidi_Default_LTR) {
bidiReq = UBIDI_DEFAULT_LTR;
} else if (bidiFlags == kBidi_Default_RTL) {
bidiReq = UBIDI_DEFAULT_RTL;
} }
} else { ubidi_setPara(mBidi, buf, mBufSize, bidiReq, NULL, &status);
if (!U_SUCCESS(status)) {
ALOGE("error calling ubidi_setPara, status = %d", status); ALOGE("error calling ubidi_setPara, status = %d", status);
return;
} }
ubidi_close(bidi); const int paraDir = ubidi_getParaLevel(mBidi) & kDirection_Mask;
} else { const ssize_t rc = ubidi_countRuns(mBidi, &status);
ALOGE("error creating bidi object"); if (!U_SUCCESS(status) || rc < 0) {
ALOGW("error counting bidi runs, status = %d", status);
} }
if (!U_SUCCESS(status) || rc <= 1) {
mIsRtl = (paraDir == kBidi_RTL);
return;
} }
if (doSingleRun) { mRunCount = rc;
doLayoutRunCached(buf, start, count, bufSize, isRtl, &ctx, start); }
void Layout::doLayout(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
int bidiFlags, const FontStyle &style, const MinikinPaint &paint) {
AutoMutex _l(gMinikinLock);
LayoutContext ctx;
ctx.style = style;
ctx.paint = paint;
reset();
mAdvances.resize(count, 0);
for (const BidiText::Iter::RunInfo& runInfo : BidiText(buf, start, count, bufSize, bidiFlags)) {
doLayoutRunCached(buf, runInfo.mRunStart, runInfo.mRunLength, bufSize, runInfo.mIsRtl, &ctx,
start);
} }
ctx.clearHbFonts(); ctx.clearHbFonts();
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册