1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "TextLayout" 18 19 #include "TextLayout.h" 20 #include "TextLayoutCache.h" 21 22 #include <android_runtime/AndroidRuntime.h> 23 24 #include "SkTemplates.h" 25 #include "unicode/ubidi.h" 26 #include "unicode/ushape.h" 27 #include <utils/Log.h> 28 29 namespace android { 30 31 // Returns true if we might need layout. If bidiFlags force LTR, assume no layout, if 32 // bidiFlags indicate there probably is RTL, assume we do, otherwise scan the text 33 // looking for a character >= the first RTL character in unicode and assume we do if 34 // we find one. 35 bool TextLayout::needsLayout(const jchar* text, jint len, jint bidiFlags) { 36 if (bidiFlags == kBidi_Force_LTR) { 37 return false; 38 } 39 if ((bidiFlags == kBidi_RTL) || (bidiFlags == kBidi_Default_RTL) || 40 bidiFlags == kBidi_Force_RTL) { 41 return true; 42 } 43 for (int i = 0; i < len; ++i) { 44 if (text[i] >= UNICODE_FIRST_RTL_CHAR) { 45 return true; 46 } 47 } 48 return false; 49 } 50 51 // Draws or gets the path of a paragraph of text on a single line, running bidi and shaping. 52 // This will draw if canvas is not null, otherwise path must be non-null and it will create 53 // a path representing the text that would have been drawn. 54 void TextLayout::handleText(SkPaint *paint, const jchar* text, jsize len, 55 jint bidiFlags, jfloat x, jfloat y, SkPath *path) { 56 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint, 57 text, 0, len, len, bidiFlags); 58 if (value == NULL) { 59 return ; 60 } 61 SkScalar x_ = SkFloatToScalar(x); 62 SkScalar y_ = SkFloatToScalar(y); 63 // Beware: this needs Glyph encoding (already done on the Paint constructor) 64 paint->getTextPath(value->getGlyphs(), value->getGlyphsCount() * 2, x_, y_, path); 65 } 66 67 void TextLayout::getTextRunAdvances(SkPaint* paint, const jchar* chars, jint start, 68 jint count, jint contextCount, jint dirFlags, 69 jfloat* resultAdvances, jfloat* resultTotalAdvance) { 70 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint, 71 chars, start, count, contextCount, dirFlags); 72 if (value == NULL) { 73 return ; 74 } 75 if (resultAdvances) { 76 memcpy(resultAdvances, value->getAdvances(), value->getAdvancesCount() * sizeof(jfloat)); 77 } 78 if (resultTotalAdvance) { 79 *resultTotalAdvance = value->getTotalAdvance(); 80 } 81 } 82 83 void TextLayout::getTextPath(SkPaint *paint, const jchar *text, jsize len, 84 jint bidiFlags, jfloat x, jfloat y, SkPath *path) { 85 handleText(paint, text, len, bidiFlags, x, y, path); 86 } 87 88 89 void TextLayout::drawTextOnPath(SkPaint* paint, const jchar* text, int count, 90 int bidiFlags, jfloat hOffset, jfloat vOffset, 91 SkPath* path, SkCanvas* canvas) { 92 93 SkScalar h_ = SkFloatToScalar(hOffset); 94 SkScalar v_ = SkFloatToScalar(vOffset); 95 96 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint, 97 text, 0, count, count, bidiFlags); 98 if (value == NULL) { 99 return; 100 } 101 102 // Beware: this needs Glyph encoding (already done on the Paint constructor) 103 canvas->drawTextOnPathHV(value->getGlyphs(), value->getGlyphsCount() * 2, *path, h_, v_, *paint); 104 } 105 106 } 107