Loading core/jni/Android.mk +3 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ LOCAL_SRC_FILES:= \ android/graphics/DrawFilter.cpp \ android/graphics/CreateJavaOutputStreamAdaptor.cpp \ android/graphics/Graphics.cpp \ android/graphics/HarfbuzzSkia.cpp \ android/graphics/Interpolator.cpp \ android/graphics/LayerRasterizer.cpp \ android/graphics/MaskFilter.cpp \ Loading Loading @@ -174,6 +175,7 @@ LOCAL_C_INCLUDES += \ external/icu4c/i18n \ external/icu4c/common \ external/jpeg \ external/harfbuzz/src \ frameworks/opt/emoji LOCAL_SHARED_LIBRARIES := \ Loading Loading @@ -206,6 +208,7 @@ LOCAL_SHARED_LIBRARIES := \ libjpeg \ libnfc_ndef \ libusbhost \ libharfbuzz \ ifeq ($(USE_OPENGL_RENDERER),true) LOCAL_SHARED_LIBRARIES += libhwui Loading core/jni/android/graphics/Canvas.cpp +23 −0 Original line number Diff line number Diff line Loading @@ -755,6 +755,27 @@ public: env->ReleaseStringChars(text, textArray); } static void drawGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, jcharArray glyphs, int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) { jchar* glyphArray = env->GetCharArrayElements(glyphs, NULL); // TODO: need to suppress this code after the GL renderer is modified for not // copying the paint // Save old text encoding SkPaint::TextEncoding oldEncoding = paint->getTextEncoding(); // Define Glyph encoding paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); TextLayout::drawText(paint, glyphArray + index, count, flags, x, y, canvas); // Get back old encoding paint->setTextEncoding(oldEncoding); env->ReleaseCharArrayElements(glyphs, glyphArray, JNI_ABORT); } static void drawTextRun___CIIIIFFIPaint( JNIEnv* env, jobject, SkCanvas* canvas, jcharArray text, int index, int count, int contextIndex, int contextCount, Loading Loading @@ -946,6 +967,8 @@ static JNINativeMethod gCanvasMethods[] = { (void*) SkCanvasGlue::drawText___CIIFFIPaint}, {"native_drawText","(ILjava/lang/String;IIFFII)V", (void*) SkCanvasGlue::drawText__StringIIFFIPaint}, {"native_drawGlyphs","(I[CIIFFII)V", (void*) SkCanvasGlue::drawGlyphs___CIIFFIPaint}, {"native_drawTextRun","(I[CIIIIFFII)V", (void*) SkCanvasGlue::drawTextRun___CIIIIFFIPaint}, {"native_drawTextRun","(ILjava/lang/String;IIIIFFII)V", Loading core/jni/android/graphics/HarfbuzzSkia.cpp 0 → 100644 +239 −0 Original line number Diff line number Diff line /* * Copyright 2011, The Android Open Source Project * Copyright 2011, Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "HarfbuzzSkia.h" #include "SkFontHost.h" #include "SkPaint.h" #include "SkPath.h" #include "SkPoint.h" #include "SkRect.h" #include "SkTypeface.h" extern "C" { #include "harfbuzz-shaper.h" } // This file implements the callbacks which Harfbuzz requires by using Skia // calls. See the Harfbuzz source for references about what these callbacks do. namespace android { static HB_Fixed SkiaScalarToHarfbuzzFixed(SkScalar value) { // HB_Fixed is a 26.6 fixed point format. return value * 64; } static void setupPaintWithFontData(SkPaint* paint, FontData* data) { paint->setAntiAlias(true); paint->setSubpixelText(true); paint->setHinting(SkPaint::kSlight_Hinting); paint->setTextSize(SkFloatToScalar(data->textSize)); paint->setTypeface(data->typeFace); paint->setFakeBoldText(data->fakeBold); paint->setTextSkewX(data->fakeItalic ? -SK_Scalar1/4 : 0); } static HB_Bool stringToGlyphs(HB_Font hbFont, const HB_UChar16* characters, hb_uint32 length, HB_Glyph* glyphs, hb_uint32* glyphsSize, HB_Bool isRTL) { FontData* data = reinterpret_cast<FontData*>(hbFont->userData); SkPaint paint; setupPaintWithFontData(&paint, data); paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); int numGlyphs = paint.textToGlyphs(characters, length * sizeof(uint16_t), reinterpret_cast<uint16_t*>(glyphs)); // HB_Glyph is 32-bit, but Skia outputs only 16-bit numbers. So our // |glyphs| array needs to be converted. for (int i = numGlyphs - 1; i >= 0; --i) { uint16_t value; // We use a memcpy to avoid breaking strict aliasing rules. memcpy(&value, reinterpret_cast<char*>(glyphs) + sizeof(uint16_t) * i, sizeof(value)); glyphs[i] = value; } *glyphsSize = numGlyphs; return 1; } static void glyphsToAdvances(HB_Font hbFont, const HB_Glyph* glyphs, hb_uint32 numGlyphs, HB_Fixed* advances, int flags) { FontData* data = reinterpret_cast<FontData*>(hbFont->userData); SkPaint paint; setupPaintWithFontData(&paint, data); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); uint16_t* glyphs16 = new uint16_t[numGlyphs]; if (!glyphs16) return; for (unsigned i = 0; i < numGlyphs; ++i) glyphs16[i] = glyphs[i]; paint.getTextWidths(glyphs16, numGlyphs * sizeof(uint16_t), reinterpret_cast<SkScalar*>(advances)); // The |advances| values which Skia outputs are SkScalars, which are floats // in Chromium. However, Harfbuzz wants them in 26.6 fixed point format. // These two formats are both 32-bits long. for (unsigned i = 0; i < numGlyphs; ++i) { float value; // We use a memcpy to avoid breaking strict aliasing rules. memcpy(&value, reinterpret_cast<char*>(advances) + sizeof(float) * i, sizeof(value)); advances[i] = SkiaScalarToHarfbuzzFixed(value); } delete glyphs16; } static HB_Bool canRender(HB_Font hbFont, const HB_UChar16* characters, hb_uint32 length) { FontData* data = reinterpret_cast<FontData*>(hbFont->userData); SkPaint paint; setupPaintWithFontData(&paint, data); paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); uint16_t* glyphs16 = new uint16_t[length]; int numGlyphs = paint.textToGlyphs(characters, length * sizeof(uint16_t), glyphs16); bool result = true; for (int i = 0; i < numGlyphs; ++i) { if (!glyphs16[i]) { result = false; break; } } delete glyphs16; return result; } static HB_Error getOutlinePoint(HB_Font hbFont, HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed* xPos, HB_Fixed* yPos, hb_uint32* resultingNumPoints) { FontData* data = reinterpret_cast<FontData*>(hbFont->userData); SkPaint paint; setupPaintWithFontData(&paint, data); if (flags & HB_ShaperFlag_UseDesignMetrics) // This is requesting pre-hinted positions. We can't support this. return HB_Err_Invalid_Argument; paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); uint16_t glyph16 = glyph; SkPath path; paint.getTextPath(&glyph16, sizeof(glyph16), 0, 0, &path); uint32_t numPoints = path.getPoints(0, 0); if (point >= numPoints) return HB_Err_Invalid_SubTable; SkPoint* points = reinterpret_cast<SkPoint*>(malloc(sizeof(SkPoint) * (point + 1))); if (!points) return HB_Err_Invalid_SubTable; // Skia does let us get a single point from the path. path.getPoints(points, point + 1); *xPos = SkiaScalarToHarfbuzzFixed(points[point].fX); *yPos = SkiaScalarToHarfbuzzFixed(points[point].fY); *resultingNumPoints = numPoints; delete points; return HB_Err_Ok; } static void getGlyphMetrics(HB_Font hbFont, HB_Glyph glyph, HB_GlyphMetrics* metrics) { FontData* data = reinterpret_cast<FontData*>(hbFont->userData); SkPaint paint; setupPaintWithFontData(&paint, data); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); uint16_t glyph16 = glyph; SkScalar width; SkRect bounds; paint.getTextWidths(&glyph16, sizeof(glyph16), &width, &bounds); metrics->x = SkiaScalarToHarfbuzzFixed(bounds.fLeft); metrics->y = SkiaScalarToHarfbuzzFixed(bounds.fTop); metrics->width = SkiaScalarToHarfbuzzFixed(bounds.width()); metrics->height = SkiaScalarToHarfbuzzFixed(bounds.height()); metrics->xOffset = SkiaScalarToHarfbuzzFixed(width); // We can't actually get the |y| correct because Skia doesn't export // the vertical advance. However, nor we do ever render vertical text at // the moment so it's unimportant. metrics->yOffset = 0; } static HB_Fixed getFontMetric(HB_Font hbFont, HB_FontMetric metric) { FontData* data = reinterpret_cast<FontData*>(hbFont->userData); SkPaint paint; setupPaintWithFontData(&paint, data); SkPaint::FontMetrics skiaMetrics; paint.getFontMetrics(&skiaMetrics); switch (metric) { case HB_FontAscent: return SkiaScalarToHarfbuzzFixed(-skiaMetrics.fAscent); // We don't support getting the rest of the metrics and Harfbuzz doesn't seem to need them. default: return 0; } return 0; } const HB_FontClass harfbuzzSkiaClass = { stringToGlyphs, glyphsToAdvances, canRender, getOutlinePoint, getGlyphMetrics, getFontMetric, }; HB_Error harfbuzzSkiaGetTable(void* voidface, const HB_Tag tag, HB_Byte* buffer, HB_UInt* len) { FontData* data = reinterpret_cast<FontData*>(voidface); SkTypeface* typeface = data->typeFace; const size_t tableSize = SkFontHost::GetTableSize(typeface->uniqueID(), tag); if (!tableSize) return HB_Err_Invalid_Argument; // If Harfbuzz specified a NULL buffer then it's asking for the size of the table. if (!buffer) { *len = tableSize; return HB_Err_Ok; } if (*len < tableSize) return HB_Err_Invalid_Argument; SkFontHost::GetTableData(typeface->uniqueID(), tag, 0, tableSize, buffer); return HB_Err_Ok; } } // namespace android core/jni/android/graphics/HarfbuzzSkia.h 0 → 100644 +48 −0 Original line number Diff line number Diff line /* * Copyright 2011, The Android Open Source Project * Copyright 2011, Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef HarfbuzzSkia_h #define HarfbuzzSkia_h #include "SkTypeface.h" extern "C" { #include "harfbuzz-shaper.h" } namespace android { typedef struct { SkTypeface* typeFace; float textSize; bool fakeBold; bool fakeItalic; } FontData; HB_Error harfbuzzSkiaGetTable(void* voidface, const HB_Tag, HB_Byte* buffer, HB_UInt* len); extern const HB_FontClass harfbuzzSkiaClass; } // namespace android #endif core/jni/android/graphics/Paint.cpp +30 −1 Original line number Diff line number Diff line Loading @@ -393,13 +393,40 @@ public: return count; } static int getTextWidths__StringII_F(JNIEnv* env, jobject clazz, SkPaint* paint, jstring text, int start, int end, jfloatArray widths) { static int getTextWidths__StringII_F(JNIEnv* env, jobject clazz, SkPaint* paint, jstring text, int start, int end, jfloatArray widths) { const jchar* textArray = env->GetStringChars(text, NULL); int count = dotextwidths(env, paint, textArray + start, end - start, widths); env->ReleaseStringChars(text, textArray); return count; } static int doTextGlyphs(JNIEnv* env, SkPaint* paint, const jchar* text, jint start, jint count, jint contextCount, jint flags, jcharArray glyphs) { jchar* glyphsArray = env->GetCharArrayElements(glyphs, NULL); HB_ShaperItem shaperItem; HB_FontRec font; FontData fontData; RunAdvanceDescription::shapeWithHarfbuzz(&shaperItem, &font, &fontData, paint, text, start, count, contextCount, flags); int glyphCount = shaperItem.num_glyphs; for (int i = 0; i < glyphCount; i++) { glyphsArray[i] = (jchar) shaperItem.glyphs[i]; } return glyphCount; } static int getTextGlyphs__StringIIIII_C(JNIEnv* env, jobject clazz, SkPaint* paint, jstring text, jint start, jint end, jint contextStart, jint contextEnd, jint flags, jcharArray glyphs) { const jchar* textArray = env->GetStringChars(text, NULL); int count = doTextGlyphs(env, paint, textArray + contextStart, start - contextStart, end - start, contextEnd - contextStart, flags, glyphs); env->ReleaseStringChars(text, textArray); return count; } static jfloat doTextRunAdvances(JNIEnv *env, SkPaint *paint, const jchar *text, jint start, jint count, jint contextCount, jint flags, jfloatArray advances, jint advancesIndex) { Loading Loading @@ -725,6 +752,8 @@ static JNINativeMethod methods[] = { SkPaintGlue::getTextRunAdvances___CIIIII_FI}, {"native_getTextRunAdvances","(ILjava/lang/String;IIIII[FI)F", (void*) SkPaintGlue::getTextRunAdvances__StringIIIII_FI}, {"native_getTextGlyphs","(ILjava/lang/String;IIIII[C)I", (void*) SkPaintGlue::getTextGlyphs__StringIIIII_C}, {"native_getTextRunCursor", "(I[CIIIII)I", (void*) SkPaintGlue::getTextRunCursor___C}, {"native_getTextRunCursor", "(ILjava/lang/String;IIIII)I", (void*) SkPaintGlue::getTextRunCursor__String}, Loading Loading
core/jni/Android.mk +3 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ LOCAL_SRC_FILES:= \ android/graphics/DrawFilter.cpp \ android/graphics/CreateJavaOutputStreamAdaptor.cpp \ android/graphics/Graphics.cpp \ android/graphics/HarfbuzzSkia.cpp \ android/graphics/Interpolator.cpp \ android/graphics/LayerRasterizer.cpp \ android/graphics/MaskFilter.cpp \ Loading Loading @@ -174,6 +175,7 @@ LOCAL_C_INCLUDES += \ external/icu4c/i18n \ external/icu4c/common \ external/jpeg \ external/harfbuzz/src \ frameworks/opt/emoji LOCAL_SHARED_LIBRARIES := \ Loading Loading @@ -206,6 +208,7 @@ LOCAL_SHARED_LIBRARIES := \ libjpeg \ libnfc_ndef \ libusbhost \ libharfbuzz \ ifeq ($(USE_OPENGL_RENDERER),true) LOCAL_SHARED_LIBRARIES += libhwui Loading
core/jni/android/graphics/Canvas.cpp +23 −0 Original line number Diff line number Diff line Loading @@ -755,6 +755,27 @@ public: env->ReleaseStringChars(text, textArray); } static void drawGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, jcharArray glyphs, int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) { jchar* glyphArray = env->GetCharArrayElements(glyphs, NULL); // TODO: need to suppress this code after the GL renderer is modified for not // copying the paint // Save old text encoding SkPaint::TextEncoding oldEncoding = paint->getTextEncoding(); // Define Glyph encoding paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); TextLayout::drawText(paint, glyphArray + index, count, flags, x, y, canvas); // Get back old encoding paint->setTextEncoding(oldEncoding); env->ReleaseCharArrayElements(glyphs, glyphArray, JNI_ABORT); } static void drawTextRun___CIIIIFFIPaint( JNIEnv* env, jobject, SkCanvas* canvas, jcharArray text, int index, int count, int contextIndex, int contextCount, Loading Loading @@ -946,6 +967,8 @@ static JNINativeMethod gCanvasMethods[] = { (void*) SkCanvasGlue::drawText___CIIFFIPaint}, {"native_drawText","(ILjava/lang/String;IIFFII)V", (void*) SkCanvasGlue::drawText__StringIIFFIPaint}, {"native_drawGlyphs","(I[CIIFFII)V", (void*) SkCanvasGlue::drawGlyphs___CIIFFIPaint}, {"native_drawTextRun","(I[CIIIIFFII)V", (void*) SkCanvasGlue::drawTextRun___CIIIIFFIPaint}, {"native_drawTextRun","(ILjava/lang/String;IIIIFFII)V", Loading
core/jni/android/graphics/HarfbuzzSkia.cpp 0 → 100644 +239 −0 Original line number Diff line number Diff line /* * Copyright 2011, The Android Open Source Project * Copyright 2011, Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "HarfbuzzSkia.h" #include "SkFontHost.h" #include "SkPaint.h" #include "SkPath.h" #include "SkPoint.h" #include "SkRect.h" #include "SkTypeface.h" extern "C" { #include "harfbuzz-shaper.h" } // This file implements the callbacks which Harfbuzz requires by using Skia // calls. See the Harfbuzz source for references about what these callbacks do. namespace android { static HB_Fixed SkiaScalarToHarfbuzzFixed(SkScalar value) { // HB_Fixed is a 26.6 fixed point format. return value * 64; } static void setupPaintWithFontData(SkPaint* paint, FontData* data) { paint->setAntiAlias(true); paint->setSubpixelText(true); paint->setHinting(SkPaint::kSlight_Hinting); paint->setTextSize(SkFloatToScalar(data->textSize)); paint->setTypeface(data->typeFace); paint->setFakeBoldText(data->fakeBold); paint->setTextSkewX(data->fakeItalic ? -SK_Scalar1/4 : 0); } static HB_Bool stringToGlyphs(HB_Font hbFont, const HB_UChar16* characters, hb_uint32 length, HB_Glyph* glyphs, hb_uint32* glyphsSize, HB_Bool isRTL) { FontData* data = reinterpret_cast<FontData*>(hbFont->userData); SkPaint paint; setupPaintWithFontData(&paint, data); paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); int numGlyphs = paint.textToGlyphs(characters, length * sizeof(uint16_t), reinterpret_cast<uint16_t*>(glyphs)); // HB_Glyph is 32-bit, but Skia outputs only 16-bit numbers. So our // |glyphs| array needs to be converted. for (int i = numGlyphs - 1; i >= 0; --i) { uint16_t value; // We use a memcpy to avoid breaking strict aliasing rules. memcpy(&value, reinterpret_cast<char*>(glyphs) + sizeof(uint16_t) * i, sizeof(value)); glyphs[i] = value; } *glyphsSize = numGlyphs; return 1; } static void glyphsToAdvances(HB_Font hbFont, const HB_Glyph* glyphs, hb_uint32 numGlyphs, HB_Fixed* advances, int flags) { FontData* data = reinterpret_cast<FontData*>(hbFont->userData); SkPaint paint; setupPaintWithFontData(&paint, data); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); uint16_t* glyphs16 = new uint16_t[numGlyphs]; if (!glyphs16) return; for (unsigned i = 0; i < numGlyphs; ++i) glyphs16[i] = glyphs[i]; paint.getTextWidths(glyphs16, numGlyphs * sizeof(uint16_t), reinterpret_cast<SkScalar*>(advances)); // The |advances| values which Skia outputs are SkScalars, which are floats // in Chromium. However, Harfbuzz wants them in 26.6 fixed point format. // These two formats are both 32-bits long. for (unsigned i = 0; i < numGlyphs; ++i) { float value; // We use a memcpy to avoid breaking strict aliasing rules. memcpy(&value, reinterpret_cast<char*>(advances) + sizeof(float) * i, sizeof(value)); advances[i] = SkiaScalarToHarfbuzzFixed(value); } delete glyphs16; } static HB_Bool canRender(HB_Font hbFont, const HB_UChar16* characters, hb_uint32 length) { FontData* data = reinterpret_cast<FontData*>(hbFont->userData); SkPaint paint; setupPaintWithFontData(&paint, data); paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); uint16_t* glyphs16 = new uint16_t[length]; int numGlyphs = paint.textToGlyphs(characters, length * sizeof(uint16_t), glyphs16); bool result = true; for (int i = 0; i < numGlyphs; ++i) { if (!glyphs16[i]) { result = false; break; } } delete glyphs16; return result; } static HB_Error getOutlinePoint(HB_Font hbFont, HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed* xPos, HB_Fixed* yPos, hb_uint32* resultingNumPoints) { FontData* data = reinterpret_cast<FontData*>(hbFont->userData); SkPaint paint; setupPaintWithFontData(&paint, data); if (flags & HB_ShaperFlag_UseDesignMetrics) // This is requesting pre-hinted positions. We can't support this. return HB_Err_Invalid_Argument; paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); uint16_t glyph16 = glyph; SkPath path; paint.getTextPath(&glyph16, sizeof(glyph16), 0, 0, &path); uint32_t numPoints = path.getPoints(0, 0); if (point >= numPoints) return HB_Err_Invalid_SubTable; SkPoint* points = reinterpret_cast<SkPoint*>(malloc(sizeof(SkPoint) * (point + 1))); if (!points) return HB_Err_Invalid_SubTable; // Skia does let us get a single point from the path. path.getPoints(points, point + 1); *xPos = SkiaScalarToHarfbuzzFixed(points[point].fX); *yPos = SkiaScalarToHarfbuzzFixed(points[point].fY); *resultingNumPoints = numPoints; delete points; return HB_Err_Ok; } static void getGlyphMetrics(HB_Font hbFont, HB_Glyph glyph, HB_GlyphMetrics* metrics) { FontData* data = reinterpret_cast<FontData*>(hbFont->userData); SkPaint paint; setupPaintWithFontData(&paint, data); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); uint16_t glyph16 = glyph; SkScalar width; SkRect bounds; paint.getTextWidths(&glyph16, sizeof(glyph16), &width, &bounds); metrics->x = SkiaScalarToHarfbuzzFixed(bounds.fLeft); metrics->y = SkiaScalarToHarfbuzzFixed(bounds.fTop); metrics->width = SkiaScalarToHarfbuzzFixed(bounds.width()); metrics->height = SkiaScalarToHarfbuzzFixed(bounds.height()); metrics->xOffset = SkiaScalarToHarfbuzzFixed(width); // We can't actually get the |y| correct because Skia doesn't export // the vertical advance. However, nor we do ever render vertical text at // the moment so it's unimportant. metrics->yOffset = 0; } static HB_Fixed getFontMetric(HB_Font hbFont, HB_FontMetric metric) { FontData* data = reinterpret_cast<FontData*>(hbFont->userData); SkPaint paint; setupPaintWithFontData(&paint, data); SkPaint::FontMetrics skiaMetrics; paint.getFontMetrics(&skiaMetrics); switch (metric) { case HB_FontAscent: return SkiaScalarToHarfbuzzFixed(-skiaMetrics.fAscent); // We don't support getting the rest of the metrics and Harfbuzz doesn't seem to need them. default: return 0; } return 0; } const HB_FontClass harfbuzzSkiaClass = { stringToGlyphs, glyphsToAdvances, canRender, getOutlinePoint, getGlyphMetrics, getFontMetric, }; HB_Error harfbuzzSkiaGetTable(void* voidface, const HB_Tag tag, HB_Byte* buffer, HB_UInt* len) { FontData* data = reinterpret_cast<FontData*>(voidface); SkTypeface* typeface = data->typeFace; const size_t tableSize = SkFontHost::GetTableSize(typeface->uniqueID(), tag); if (!tableSize) return HB_Err_Invalid_Argument; // If Harfbuzz specified a NULL buffer then it's asking for the size of the table. if (!buffer) { *len = tableSize; return HB_Err_Ok; } if (*len < tableSize) return HB_Err_Invalid_Argument; SkFontHost::GetTableData(typeface->uniqueID(), tag, 0, tableSize, buffer); return HB_Err_Ok; } } // namespace android
core/jni/android/graphics/HarfbuzzSkia.h 0 → 100644 +48 −0 Original line number Diff line number Diff line /* * Copyright 2011, The Android Open Source Project * Copyright 2011, Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef HarfbuzzSkia_h #define HarfbuzzSkia_h #include "SkTypeface.h" extern "C" { #include "harfbuzz-shaper.h" } namespace android { typedef struct { SkTypeface* typeFace; float textSize; bool fakeBold; bool fakeItalic; } FontData; HB_Error harfbuzzSkiaGetTable(void* voidface, const HB_Tag, HB_Byte* buffer, HB_UInt* len); extern const HB_FontClass harfbuzzSkiaClass; } // namespace android #endif
core/jni/android/graphics/Paint.cpp +30 −1 Original line number Diff line number Diff line Loading @@ -393,13 +393,40 @@ public: return count; } static int getTextWidths__StringII_F(JNIEnv* env, jobject clazz, SkPaint* paint, jstring text, int start, int end, jfloatArray widths) { static int getTextWidths__StringII_F(JNIEnv* env, jobject clazz, SkPaint* paint, jstring text, int start, int end, jfloatArray widths) { const jchar* textArray = env->GetStringChars(text, NULL); int count = dotextwidths(env, paint, textArray + start, end - start, widths); env->ReleaseStringChars(text, textArray); return count; } static int doTextGlyphs(JNIEnv* env, SkPaint* paint, const jchar* text, jint start, jint count, jint contextCount, jint flags, jcharArray glyphs) { jchar* glyphsArray = env->GetCharArrayElements(glyphs, NULL); HB_ShaperItem shaperItem; HB_FontRec font; FontData fontData; RunAdvanceDescription::shapeWithHarfbuzz(&shaperItem, &font, &fontData, paint, text, start, count, contextCount, flags); int glyphCount = shaperItem.num_glyphs; for (int i = 0; i < glyphCount; i++) { glyphsArray[i] = (jchar) shaperItem.glyphs[i]; } return glyphCount; } static int getTextGlyphs__StringIIIII_C(JNIEnv* env, jobject clazz, SkPaint* paint, jstring text, jint start, jint end, jint contextStart, jint contextEnd, jint flags, jcharArray glyphs) { const jchar* textArray = env->GetStringChars(text, NULL); int count = doTextGlyphs(env, paint, textArray + contextStart, start - contextStart, end - start, contextEnd - contextStart, flags, glyphs); env->ReleaseStringChars(text, textArray); return count; } static jfloat doTextRunAdvances(JNIEnv *env, SkPaint *paint, const jchar *text, jint start, jint count, jint contextCount, jint flags, jfloatArray advances, jint advancesIndex) { Loading Loading @@ -725,6 +752,8 @@ static JNINativeMethod methods[] = { SkPaintGlue::getTextRunAdvances___CIIIII_FI}, {"native_getTextRunAdvances","(ILjava/lang/String;IIIII[FI)F", (void*) SkPaintGlue::getTextRunAdvances__StringIIIII_FI}, {"native_getTextGlyphs","(ILjava/lang/String;IIIII[C)I", (void*) SkPaintGlue::getTextGlyphs__StringIIIII_C}, {"native_getTextRunCursor", "(I[CIIIII)I", (void*) SkPaintGlue::getTextRunCursor___C}, {"native_getTextRunCursor", "(ILjava/lang/String;IIIII)I", (void*) SkPaintGlue::getTextRunCursor__String}, Loading