@@ -308,11 +308,12 @@ TextLayoutValue::TextLayoutValue(size_t contextCount) :
308308 // Give a hint for advances and glyphs vectors size
309309 mAdvances .setCapacity (contextCount);
310310 mGlyphs .setCapacity (contextCount);
311+ mPos .setCapacity (contextCount * 2 );
311312}
312313
313314size_t TextLayoutValue::getSize () const {
314315 return sizeof (TextLayoutValue) + sizeof (jfloat) * mAdvances .capacity () +
315- sizeof (jchar) * mGlyphs .capacity ();
316+ sizeof (jchar) * mGlyphs .capacity () + sizeof (jfloat) * mPos . capacity () ;
316317}
317318
318319void TextLayoutValue::setElapsedTime (uint32_t time) {
@@ -329,13 +330,9 @@ TextLayoutShaper::TextLayoutShaper() : mShaperItemGlyphArraySize(0) {
329330 mFontRec .klass = &harfbuzzSkiaClass;
330331 mFontRec .userData = 0 ;
331332
332- // The values which harfbuzzSkiaClass returns are already scaled to
333- // pixel units, so we just set all these to one to disable further
334- // scaling.
335- mFontRec .x_ppem = 1 ;
336- mFontRec .y_ppem = 1 ;
337- mFontRec .x_scale = 1 ;
338- mFontRec .y_scale = 1 ;
333+ // Note that the scaling values (x_ and y_ppem, x_ and y_scale) will be set
334+ // below, when the paint transform and em unit of the actual shaping font
335+ // are known.
339336
340337 memset (&mShaperItem , 0 , sizeof (mShaperItem ));
341338
@@ -360,7 +357,7 @@ void TextLayoutShaper::computeValues(TextLayoutValue* value, const SkPaint* pain
360357 size_t start, size_t count, size_t contextCount, int dirFlags) {
361358
362359 computeValues (paint, chars, start, count, contextCount, dirFlags,
363- &value->mAdvances , &value->mTotalAdvance , &value->mGlyphs );
360+ &value->mAdvances , &value->mTotalAdvance , &value->mGlyphs , &value-> mPos );
364361#if DEBUG_ADVANCES
365362 ALOGD (" Advances - start = %d, count = %d, contextCount = %d, totalAdvance = %f" , start, count,
366363 contextCount, value->mTotalAdvance );
@@ -370,9 +367,9 @@ void TextLayoutShaper::computeValues(TextLayoutValue* value, const SkPaint* pain
370367void TextLayoutShaper::computeValues (const SkPaint* paint, const UChar* chars,
371368 size_t start, size_t count, size_t contextCount, int dirFlags,
372369 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
373- Vector<jchar>* const outGlyphs) {
370+ Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos) {
371+ *outTotalAdvance = 0 ;
374372 if (!count) {
375- *outTotalAdvance = 0 ;
376373 return ;
377374 }
378375
@@ -437,6 +434,7 @@ void TextLayoutShaper::computeValues(const SkPaint* paint, const UChar* chars,
437434 ALOGW (" Visual run is not valid" );
438435 outGlyphs->clear ();
439436 outAdvances->clear ();
437+ outPos->clear ();
440438 *outTotalAdvance = 0 ;
441439 isRTL = (paraDir == 1 );
442440 useSingleRun = true ;
@@ -459,15 +457,13 @@ void TextLayoutShaper::computeValues(const SkPaint* paint, const UChar* chars,
459457
460458 lengthRun = endRun - startRun;
461459 isRTL = (runDir == UBIDI_RTL);
462- jfloat runTotalAdvance = 0 ;
463460#if DEBUG_GLYPHS
464461 ALOGD (" Processing Bidi Run = %d -- run-start = %d, run-len = %d, isRTL = %d" ,
465462 i, startRun, lengthRun, isRTL);
466463#endif
467464 computeRunValues (paint, chars + startRun, lengthRun, isRTL,
468- outAdvances, &runTotalAdvance , outGlyphs);
465+ outAdvances, outTotalAdvance , outGlyphs, outPos );
469466
470- *outTotalAdvance += runTotalAdvance;
471467 }
472468 }
473469 } else {
@@ -490,7 +486,7 @@ void TextLayoutShaper::computeValues(const SkPaint* paint, const UChar* chars,
490486 " -- run-start = %d, run-len = %d, isRTL = %d" , start, count, isRTL);
491487#endif
492488 computeRunValues (paint, chars + start, count, isRTL,
493- outAdvances, outTotalAdvance, outGlyphs);
489+ outAdvances, outTotalAdvance, outGlyphs, outPos );
494490 }
495491
496492#if DEBUG_GLYPHS
@@ -512,10 +508,9 @@ static void logGlyphs(HB_ShaperItem shaperItem) {
512508void TextLayoutShaper::computeRunValues (const SkPaint* paint, const UChar* chars,
513509 size_t count, bool isRTL,
514510 Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
515- Vector<jchar>* const outGlyphs) {
511+ Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos ) {
516512 if (!count) {
517513 // We cannot shape an empty run.
518- *outTotalAdvance = 0 ;
519514 return ;
520515 }
521516
@@ -615,7 +610,8 @@ void TextLayoutShaper::computeRunValues(const SkPaint* paint, const UChar* chars
615610
616611 // Define shaping paint properties
617612 mShapingPaint .setTextSize (paint->getTextSize ());
618- mShapingPaint .setTextSkewX (paint->getTextSkewX ());
613+ float skewX = paint->getTextSkewX ();
614+ mShapingPaint .setTextSkewX (skewX);
619615 mShapingPaint .setTextScaleX (paint->getTextScaleX ());
620616 mShapingPaint .setFlags (paint->getFlags ());
621617 mShapingPaint .setHinting (paint->getHinting ());
@@ -624,7 +620,7 @@ void TextLayoutShaper::computeRunValues(const SkPaint* paint, const UChar* chars
624620 // into the shaperItem
625621 ssize_t indexFontRun = isRTL ? mShaperItem .stringLength - 1 : 0 ;
626622 unsigned numCodePoints = 0 ;
627- jfloat totalAdvance = 0 ;
623+ jfloat totalAdvance = *outTotalAdvance ;
628624 while ((isRTL) ?
629625 hb_utf16_script_run_prev (&numCodePoints, &mShaperItem .item , mShaperItem .string ,
630626 mShaperItem .stringLength , &indexFontRun):
@@ -692,7 +688,6 @@ void TextLayoutShaper::computeRunValues(const SkPaint* paint, const UChar* chars
692688 currentAdvance = HBFixedToFloat (mShaperItem .advances [i]);
693689 totalFontRunAdvance += currentAdvance;
694690 }
695- totalAdvance += totalFontRunAdvance;
696691
697692#if DEBUG_ADVANCES
698693 ALOGD (" Returned advances" );
@@ -717,6 +712,30 @@ void TextLayoutShaper::computeRunValues(const SkPaint* paint, const UChar* chars
717712 outGlyphs->add (glyph);
718713 }
719714 }
715+
716+ // Get glyph positions (and reverse them in place if RTL)
717+ if (outPos) {
718+ size_t countGlyphs = mShaperItem .num_glyphs ;
719+ jfloat x = totalAdvance;
720+ for (size_t i = 0 ; i < countGlyphs; i++) {
721+ size_t index = (!isRTL) ? i : countGlyphs - 1 - i;
722+ float xo = HBFixedToFloat (mShaperItem .offsets [index].x );
723+ float yo = HBFixedToFloat (mShaperItem .offsets [index].y );
724+ // Apply skewX component of transform to position offsets. Note
725+ // that scale has already been applied through x_ and y_scale
726+ // set in the mFontRec.
727+ outPos->add (x + xo + yo * skewX);
728+ outPos->add (yo);
729+ #ifdef DEBUG_GLYPHS
730+ ALOGD (" -- hb adv[%d] = %f, log_cluster[%d] = %d" ,
731+ index, HBFixedToFloat (mShaperItem .advances [index]),
732+ index, mShaperItem .log_clusters [index]);
733+ #endif
734+ x += HBFixedToFloat (mShaperItem .advances [index]);
735+ }
736+ }
737+
738+ totalAdvance += totalFontRunAdvance;
720739 }
721740
722741 *outTotalAdvance = totalAdvance;
@@ -807,6 +826,19 @@ size_t TextLayoutShaper::shapeFontRun(const SkPaint* paint, bool isRTL) {
807826 mShapingPaint .setTypeface (typeface);
808827 mShaperItem .face = getCachedHBFace (typeface);
809828
829+ int textSize = paint->getTextSize ();
830+ float scaleX = paint->getTextScaleX ();
831+ mFontRec .x_ppem = floor (scaleX * textSize + 0.5 );
832+ mFontRec .y_ppem = textSize;
833+ uint32_t unitsPerEm = SkFontHost::GetUnitsPerEm (typeface->uniqueID ());
834+ // x_ and y_scale are the conversion factors from font design space
835+ // (unitsPerEm) to 1/64th of device pixels in 16.16 format.
836+ const int kDevicePixelFraction = 64 ;
837+ const int kMultiplyFor16Dot16 = 1 << 16 ;
838+ float emScale = kDevicePixelFraction * kMultiplyFor16Dot16 / (float )unitsPerEm;
839+ mFontRec .x_scale = emScale * scaleX * textSize;
840+ mFontRec .y_scale = emScale * textSize;
841+
810842#if DEBUG_GLYPHS
811843 ALOGD (" Run typeface = %p, uniqueID = %d, hb_face = %p" ,
812844 typeface, typeface->uniqueID (), mShaperItem .face );
0 commit comments