rsFont.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879
  1. /*
  2. * Copyright (C) 2009 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. #include "rsContext.h"
  17. #include "rs.h"
  18. #include "rsFont.h"
  19. #include "rsProgramFragment.h"
  20. #include "rsMesh.h"
  21. #ifndef ANDROID_RS_SERIALIZE
  22. #include <ft2build.h>
  23. #include FT_FREETYPE_H
  24. #include FT_BITMAP_H
  25. #endif //ANDROID_RS_SERIALIZE
  26. #include <string.h>
  27. namespace android {
  28. namespace renderscript {
  29. Font::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL) {
  30. mInitialized = false;
  31. mHasKerning = false;
  32. mFace = nullptr;
  33. }
  34. bool Font::init(const char *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) {
  35. #ifndef ANDROID_RS_SERIALIZE
  36. if (mInitialized) {
  37. ALOGE("Reinitialization of fonts not supported");
  38. return false;
  39. }
  40. FT_Error error = 0;
  41. if (data != nullptr && dataLen > 0) {
  42. error = FT_New_Memory_Face(mRSC->mStateFont.getLib(), (const FT_Byte*)data, dataLen, 0, &mFace);
  43. } else {
  44. error = FT_New_Face(mRSC->mStateFont.getLib(), name, 0, &mFace);
  45. }
  46. if (error) {
  47. ALOGE("Unable to initialize font %s", name);
  48. return false;
  49. }
  50. mFontName = rsuCopyString(name);
  51. mFontSize = fontSize;
  52. mDpi = dpi;
  53. error = FT_Set_Char_Size(mFace, (FT_F26Dot6)(fontSize * 64.0f), 0, dpi, 0);
  54. if (error) {
  55. ALOGE("Unable to set font size on %s", name);
  56. return false;
  57. }
  58. mHasKerning = FT_HAS_KERNING(mFace);
  59. mInitialized = true;
  60. #endif //ANDROID_RS_SERIALIZE
  61. return true;
  62. }
  63. void Font::preDestroy() const {
  64. auto& activeFonts = mRSC->mStateFont.mActiveFonts;
  65. for (uint32_t ct = 0; ct < activeFonts.size(); ct++) {
  66. if (activeFonts[ct] == this) {
  67. activeFonts.erase(activeFonts.begin() + ct);
  68. break;
  69. }
  70. }
  71. }
  72. void Font::invalidateTextureCache() {
  73. for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) {
  74. mCachedGlyphs.valueAt(i)->mIsValid = false;
  75. }
  76. }
  77. void Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y) {
  78. FontState *state = &mRSC->mStateFont;
  79. int32_t nPenX = x + glyph->mBitmapLeft;
  80. int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight;
  81. float u1 = glyph->mBitmapMinU;
  82. float u2 = glyph->mBitmapMaxU;
  83. float v1 = glyph->mBitmapMinV;
  84. float v2 = glyph->mBitmapMaxV;
  85. int32_t width = (int32_t) glyph->mBitmapWidth;
  86. int32_t height = (int32_t) glyph->mBitmapHeight;
  87. state->appendMeshQuad(nPenX, nPenY, 0, u1, v2,
  88. nPenX + width, nPenY, 0, u2, v2,
  89. nPenX + width, nPenY - height, 0, u2, v1,
  90. nPenX, nPenY - height, 0, u1, v1);
  91. }
  92. void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y,
  93. uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) {
  94. int32_t nPenX = x + glyph->mBitmapLeft;
  95. int32_t nPenY = y + glyph->mBitmapTop;
  96. uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth;
  97. uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight;
  98. FontState *state = &mRSC->mStateFont;
  99. uint32_t cacheWidth = state->getCacheTextureType()->getDimX();
  100. const uint8_t* cacheBuffer = state->mCacheBuffer;
  101. uint32_t cacheX = 0, cacheY = 0;
  102. int32_t bX = 0, bY = 0;
  103. for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) {
  104. for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) {
  105. if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) {
  106. ALOGE("Skipping invalid index");
  107. continue;
  108. }
  109. uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX];
  110. bitmap[bY * bitmapW + bX] = tempCol;
  111. }
  112. }
  113. }
  114. void Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) {
  115. int32_t nPenX = x + glyph->mBitmapLeft;
  116. int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight;
  117. int32_t width = (int32_t) glyph->mBitmapWidth;
  118. int32_t height = (int32_t) glyph->mBitmapHeight;
  119. // 0, 0 is top left, so bottom is a positive number
  120. if (bounds->bottom < nPenY) {
  121. bounds->bottom = nPenY;
  122. }
  123. if (bounds->left > nPenX) {
  124. bounds->left = nPenX;
  125. }
  126. if (bounds->right < nPenX + width) {
  127. bounds->right = nPenX + width;
  128. }
  129. if (bounds->top > nPenY - height) {
  130. bounds->top = nPenY - height;
  131. }
  132. }
  133. void Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y,
  134. uint32_t start, int32_t numGlyphs,
  135. RenderMode mode, Rect *bounds,
  136. uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) {
  137. if (!mInitialized || numGlyphs == 0 || text == nullptr || len == 0) {
  138. return;
  139. }
  140. if (mode == Font::MEASURE) {
  141. if (bounds == nullptr) {
  142. ALOGE("No return rectangle provided to measure text");
  143. return;
  144. }
  145. // Reset min and max of the bounding box to something large
  146. bounds->set(1e6, -1e6, 1e6, -1e6);
  147. }
  148. int32_t penX = x, penY = y;
  149. int32_t glyphsLeft = 1;
  150. if (numGlyphs > 0) {
  151. glyphsLeft = numGlyphs;
  152. }
  153. size_t index = start;
  154. size_t nextIndex = 0;
  155. while (glyphsLeft > 0) {
  156. int32_t utfChar = utf32_from_utf8_at(text, len, index, &nextIndex);
  157. // Reached the end of the string or encountered
  158. if (utfChar < 0) {
  159. break;
  160. }
  161. // Move to the next character in the array
  162. index = nextIndex;
  163. CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar);
  164. // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage
  165. if (cachedGlyph->mIsValid) {
  166. switch (mode) {
  167. case FRAMEBUFFER:
  168. drawCachedGlyph(cachedGlyph, penX, penY);
  169. break;
  170. case BITMAP:
  171. drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH);
  172. break;
  173. case MEASURE:
  174. measureCachedGlyph(cachedGlyph, penX, penY, bounds);
  175. break;
  176. }
  177. }
  178. penX += (cachedGlyph->mAdvanceX >> 6);
  179. // If we were given a specific number of glyphs, decrement
  180. if (numGlyphs > 0) {
  181. glyphsLeft --;
  182. }
  183. }
  184. }
  185. Font::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) {
  186. CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar);
  187. if (cachedGlyph == nullptr) {
  188. cachedGlyph = cacheGlyph((uint32_t)utfChar);
  189. }
  190. // Is the glyph still in texture cache?
  191. if (!cachedGlyph->mIsValid) {
  192. updateGlyphCache(cachedGlyph);
  193. }
  194. return cachedGlyph;
  195. }
  196. void Font::updateGlyphCache(CachedGlyphInfo *glyph) {
  197. #ifndef ANDROID_RS_SERIALIZE
  198. FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER );
  199. if (error) {
  200. ALOGE("Couldn't load glyph.");
  201. return;
  202. }
  203. glyph->mAdvanceX = mFace->glyph->advance.x;
  204. glyph->mAdvanceY = mFace->glyph->advance.y;
  205. glyph->mBitmapLeft = mFace->glyph->bitmap_left;
  206. glyph->mBitmapTop = mFace->glyph->bitmap_top;
  207. FT_Bitmap *bitmap = &mFace->glyph->bitmap;
  208. // Now copy the bitmap into the cache texture
  209. uint32_t startX = 0;
  210. uint32_t startY = 0;
  211. // Let the font state figure out where to put the bitmap
  212. FontState *state = &mRSC->mStateFont;
  213. glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY);
  214. if (!glyph->mIsValid) {
  215. return;
  216. }
  217. uint32_t endX = startX + bitmap->width;
  218. uint32_t endY = startY + bitmap->rows;
  219. glyph->mBitmapMinX = startX;
  220. glyph->mBitmapMinY = startY;
  221. glyph->mBitmapWidth = bitmap->width;
  222. glyph->mBitmapHeight = bitmap->rows;
  223. uint32_t cacheWidth = state->getCacheTextureType()->getDimX();
  224. uint32_t cacheHeight = state->getCacheTextureType()->getDimY();
  225. glyph->mBitmapMinU = (float)startX / (float)cacheWidth;
  226. glyph->mBitmapMinV = (float)startY / (float)cacheHeight;
  227. glyph->mBitmapMaxU = (float)endX / (float)cacheWidth;
  228. glyph->mBitmapMaxV = (float)endY / (float)cacheHeight;
  229. #endif //ANDROID_RS_SERIALIZE
  230. }
  231. Font::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) {
  232. CachedGlyphInfo *newGlyph = new CachedGlyphInfo();
  233. mCachedGlyphs.add(glyph, newGlyph);
  234. #ifndef ANDROID_RS_SERIALIZE
  235. newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph);
  236. newGlyph->mIsValid = false;
  237. #endif //ANDROID_RS_SERIALIZE
  238. updateGlyphCache(newGlyph);
  239. return newGlyph;
  240. }
  241. Font * Font::create(Context *rsc, const char *name, float fontSize, uint32_t dpi,
  242. const void *data, uint32_t dataLen) {
  243. rsc->mStateFont.checkInit();
  244. auto& activeFonts = rsc->mStateFont.mActiveFonts;
  245. for (uint32_t i = 0; i < activeFonts.size(); i ++) {
  246. Font *ithFont = activeFonts[i];
  247. if (ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) {
  248. return ithFont;
  249. }
  250. }
  251. Font *newFont = new Font(rsc);
  252. bool isInitialized = newFont->init(name, fontSize, dpi, data, dataLen);
  253. if (isInitialized) {
  254. activeFonts.push_back(newFont);
  255. rsc->mStateFont.precacheLatin(newFont);
  256. return newFont;
  257. }
  258. ObjectBase::checkDelete(newFont);
  259. return nullptr;
  260. }
  261. Font::~Font() {
  262. #ifndef ANDROID_RS_SERIALIZE
  263. if (mFace) {
  264. FT_Done_Face(mFace);
  265. }
  266. #endif
  267. for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) {
  268. CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i);
  269. delete glyph;
  270. }
  271. }
  272. FontState::FontState() {
  273. mInitialized = false;
  274. mMaxNumberOfQuads = 1024;
  275. mCurrentQuadIndex = 0;
  276. mRSC = nullptr;
  277. #ifndef ANDROID_RS_SERIALIZE
  278. mLibrary = nullptr;
  279. #endif //ANDROID_RS_SERIALIZE
  280. float gamma = DEFAULT_TEXT_GAMMA;
  281. int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD;
  282. int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD;
  283. #ifdef __ANDROID__
  284. // Get the renderer properties
  285. char property[PROP_VALUE_MAX];
  286. // Get the gamma
  287. if (property_get(PROPERTY_TEXT_GAMMA, property, nullptr) > 0) {
  288. gamma = atof(property);
  289. }
  290. // Get the black gamma threshold
  291. if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, nullptr) > 0) {
  292. blackThreshold = atoi(property);
  293. }
  294. // Get the white gamma threshold
  295. if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, nullptr) > 0) {
  296. whiteThreshold = atoi(property);
  297. }
  298. #endif
  299. mBlackThreshold = (float)(blackThreshold) / 255.0f;
  300. mWhiteThreshold = (float)(whiteThreshold) / 255.0f;
  301. // Compute the gamma tables
  302. mBlackGamma = gamma;
  303. mWhiteGamma = 1.0f / gamma;
  304. setFontColor(0.1f, 0.1f, 0.1f, 1.0f);
  305. }
  306. FontState::~FontState() {
  307. for (uint32_t i = 0; i < mCacheLines.size(); i ++) {
  308. delete mCacheLines[i];
  309. }
  310. rsAssert(!mActiveFonts.size());
  311. }
  312. #ifndef ANDROID_RS_SERIALIZE
  313. FT_Library FontState::getLib() {
  314. if (!mLibrary) {
  315. FT_Error error = FT_Init_FreeType(&mLibrary);
  316. if (error) {
  317. ALOGE("Unable to initialize freetype");
  318. return nullptr;
  319. }
  320. }
  321. return mLibrary;
  322. }
  323. #endif //ANDROID_RS_SERIALIZE
  324. void FontState::init(Context *rsc) {
  325. mRSC = rsc;
  326. }
  327. void FontState::flushAllAndInvalidate() {
  328. if (mCurrentQuadIndex != 0) {
  329. issueDrawCommand();
  330. mCurrentQuadIndex = 0;
  331. }
  332. for (uint32_t i = 0; i < mActiveFonts.size(); i ++) {
  333. mActiveFonts[i]->invalidateTextureCache();
  334. }
  335. for (uint32_t i = 0; i < mCacheLines.size(); i ++) {
  336. mCacheLines[i]->mCurrentCol = 0;
  337. }
  338. }
  339. #ifndef ANDROID_RS_SERIALIZE
  340. bool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) {
  341. // If the glyph is too tall, don't cache it
  342. if ((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) {
  343. ALOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows);
  344. return false;
  345. }
  346. // Now copy the bitmap into the cache texture
  347. uint32_t startX = 0;
  348. uint32_t startY = 0;
  349. bool bitmapFit = false;
  350. for (uint32_t i = 0; i < mCacheLines.size(); i ++) {
  351. bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY);
  352. if (bitmapFit) {
  353. break;
  354. }
  355. }
  356. // If the new glyph didn't fit, flush the state so far and invalidate everything
  357. if (!bitmapFit) {
  358. flushAllAndInvalidate();
  359. // Try to fit it again
  360. for (uint32_t i = 0; i < mCacheLines.size(); i ++) {
  361. bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY);
  362. if (bitmapFit) {
  363. break;
  364. }
  365. }
  366. // if we still don't fit, something is wrong and we shouldn't draw
  367. if (!bitmapFit) {
  368. ALOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows);
  369. return false;
  370. }
  371. }
  372. *retOriginX = startX;
  373. *retOriginY = startY;
  374. uint32_t endX = startX + bitmap->width;
  375. uint32_t endY = startY + bitmap->rows;
  376. uint32_t cacheWidth = getCacheTextureType()->getDimX();
  377. uint8_t *cacheBuffer = mCacheBuffer;
  378. uint8_t *bitmapBuffer = bitmap->buffer;
  379. uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0;
  380. for (cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) {
  381. for (cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) {
  382. uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX];
  383. cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol;
  384. }
  385. }
  386. // This will dirty the texture and the shader so next time
  387. // we draw it will upload the data
  388. mRSC->mHal.funcs.allocation.data2D(mRSC, mTextTexture.get(), 0, 0, 0,
  389. RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, mCacheWidth, mCacheHeight,
  390. mCacheBuffer, mCacheWidth*mCacheHeight, mCacheWidth);
  391. mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get());
  392. // Some debug code
  393. /*for (uint32_t i = 0; i < mCacheLines.size(); i ++) {
  394. ALOGE("Cache Line: H: %u Empty Space: %f",
  395. mCacheLines[i]->mMaxHeight,
  396. (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f);
  397. }*/
  398. return true;
  399. }
  400. #endif //ANDROID_RS_SERIALIZE
  401. void FontState::initRenderState() {
  402. const char *shaderString = "varying vec2 varTex0;\n"
  403. "void main() {\n"
  404. " lowp vec4 col = UNI_Color;\n"
  405. " col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n"
  406. " col.a = pow(col.a, UNI_Gamma);\n"
  407. " gl_FragColor = col;\n"
  408. "}\n";
  409. const char *textureNames[] = { "Tex0" };
  410. const size_t textureNamesLengths[] = { 4 };
  411. size_t numTextures = sizeof(textureNamesLengths)/sizeof(*textureNamesLengths);
  412. ObjectBaseRef<const Element> colorElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32,
  413. RS_KIND_USER, false, 4);
  414. ObjectBaseRef<const Element> gammaElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32,
  415. RS_KIND_USER, false, 1);
  416. const char *ebn1[] = { "Color", "Gamma" };
  417. const Element *ebe1[] = {colorElem.get(), gammaElem.get()};
  418. ObjectBaseRef<const Element> constInput = Element::create(mRSC, 2, ebe1, ebn1);
  419. ObjectBaseRef<Type> inputType = Type::getTypeRef(mRSC, constInput.get(), 1);
  420. uintptr_t tmp[4];
  421. tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
  422. tmp[1] = (uintptr_t)inputType.get();
  423. tmp[2] = RS_PROGRAM_PARAM_TEXTURE_TYPE;
  424. tmp[3] = RS_TEXTURE_2D;
  425. mFontShaderFConstant.set(Allocation::createAllocation(mRSC, inputType.get(),
  426. RS_ALLOCATION_USAGE_SCRIPT |
  427. RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS));
  428. ProgramFragment *pf = new ProgramFragment(mRSC, shaderString, strlen(shaderString),
  429. textureNames, numTextures, textureNamesLengths,
  430. tmp, 4);
  431. mFontShaderF.set(pf);
  432. mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0);
  433. mFontSampler.set(Sampler::getSampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST,
  434. RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP,
  435. RS_SAMPLER_CLAMP).get());
  436. mFontShaderF->bindSampler(mRSC, 0, mFontSampler.get());
  437. mFontProgramStore.set(ProgramStore::getProgramStore(mRSC, true, true, true, true,
  438. false, false,
  439. RS_BLEND_SRC_SRC_ALPHA,
  440. RS_BLEND_DST_ONE_MINUS_SRC_ALPHA,
  441. RS_DEPTH_FUNC_ALWAYS).get());
  442. mFontProgramStore->init();
  443. }
  444. void FontState::initTextTexture() {
  445. ObjectBaseRef<const Element> alphaElem = Element::createRef(mRSC, RS_TYPE_UNSIGNED_8,
  446. RS_KIND_PIXEL_A, true, 1);
  447. // We will allocate a texture to initially hold 32 character bitmaps
  448. mCacheHeight = 256;
  449. mCacheWidth = 1024;
  450. ObjectBaseRef<Type> texType = Type::getTypeRef(mRSC, alphaElem.get(), mCacheWidth, mCacheHeight);
  451. mCacheBuffer = new uint8_t[mCacheWidth * mCacheHeight];
  452. Allocation *cacheAlloc = Allocation::createAllocation(mRSC, texType.get(),
  453. RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE);
  454. mTextTexture.set(cacheAlloc);
  455. // Split up our cache texture into lines of certain widths
  456. int32_t nextLine = 0;
  457. mCacheLines.push_back(new CacheTextureLine(16, texType->getDimX(), nextLine, 0));
  458. nextLine += mCacheLines.back()->mMaxHeight;
  459. mCacheLines.push_back(new CacheTextureLine(24, texType->getDimX(), nextLine, 0));
  460. nextLine += mCacheLines.back()->mMaxHeight;
  461. mCacheLines.push_back(new CacheTextureLine(24, texType->getDimX(), nextLine, 0));
  462. nextLine += mCacheLines.back()->mMaxHeight;
  463. mCacheLines.push_back(new CacheTextureLine(32, texType->getDimX(), nextLine, 0));
  464. nextLine += mCacheLines.back()->mMaxHeight;
  465. mCacheLines.push_back(new CacheTextureLine(32, texType->getDimX(), nextLine, 0));
  466. nextLine += mCacheLines.back()->mMaxHeight;
  467. mCacheLines.push_back(new CacheTextureLine(40, texType->getDimX(), nextLine, 0));
  468. nextLine += mCacheLines.back()->mMaxHeight;
  469. mCacheLines.push_back(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0));
  470. }
  471. // Avoid having to reallocate memory and render quad by quad
  472. void FontState::initVertexArrayBuffers() {
  473. // Now lets write index data
  474. ObjectBaseRef<const Element> indexElem = Element::createRef(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1);
  475. ObjectBaseRef<Type> indexType = Type::getTypeRef(mRSC, indexElem.get(), mMaxNumberOfQuads * 6);
  476. Allocation *indexAlloc = Allocation::createAllocation(mRSC, indexType.get(),
  477. RS_ALLOCATION_USAGE_SCRIPT |
  478. RS_ALLOCATION_USAGE_GRAPHICS_VERTEX);
  479. uint16_t *indexPtr = (uint16_t*)mRSC->mHal.funcs.allocation.lock1D(mRSC, indexAlloc);
  480. // Four verts, two triangles , six indices per quad
  481. for (uint32_t i = 0; i < mMaxNumberOfQuads; i ++) {
  482. int32_t i6 = i * 6;
  483. int32_t i4 = i * 4;
  484. indexPtr[i6 + 0] = i4 + 0;
  485. indexPtr[i6 + 1] = i4 + 1;
  486. indexPtr[i6 + 2] = i4 + 2;
  487. indexPtr[i6 + 3] = i4 + 0;
  488. indexPtr[i6 + 4] = i4 + 2;
  489. indexPtr[i6 + 5] = i4 + 3;
  490. }
  491. indexAlloc->sendDirty(mRSC);
  492. ObjectBaseRef<const Element> posElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3);
  493. ObjectBaseRef<const Element> texElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2);
  494. const char *ebn1[] = { "position", "texture0" };
  495. const Element *ebe1[] = {posElem.get(), texElem.get()};
  496. ObjectBaseRef<const Element> vertexDataElem = Element::create(mRSC, 2, ebe1, ebn1);
  497. ObjectBaseRef<Type> vertexDataType = Type::getTypeRef(mRSC, vertexDataElem.get(), mMaxNumberOfQuads * 4);
  498. Allocation *vertexAlloc = Allocation::createAllocation(mRSC, vertexDataType.get(),
  499. RS_ALLOCATION_USAGE_SCRIPT);
  500. mTextMeshPtr = (float*)mRSC->mHal.funcs.allocation.lock1D(mRSC, vertexAlloc);
  501. mMesh.set(new Mesh(mRSC, 1, 1));
  502. mMesh->setVertexBuffer(vertexAlloc, 0);
  503. mMesh->setPrimitive(indexAlloc, RS_PRIMITIVE_TRIANGLE, 0);
  504. mMesh->init();
  505. mRSC->mHal.funcs.allocation.unlock1D(mRSC, indexAlloc);
  506. mRSC->mHal.funcs.allocation.unlock1D(mRSC, vertexAlloc);
  507. }
  508. // We don't want to allocate anything unless we actually draw text
  509. void FontState::checkInit() {
  510. if (mInitialized) {
  511. return;
  512. }
  513. initTextTexture();
  514. initRenderState();
  515. initVertexArrayBuffers();
  516. // We store a string with letters in a rough frequency of occurrence
  517. mLatinPrecache = " eisarntolcdugpmhbyfvkwzxjq"
  518. "EISARNTOLCDUGPMHBYFVKWZXJQ"
  519. ",.?!()-+@;:`'0123456789";
  520. mInitialized = true;
  521. }
  522. void FontState::issueDrawCommand() {
  523. Context::PushState ps(mRSC);
  524. mRSC->setProgramVertex(mRSC->getDefaultProgramVertex());
  525. mRSC->setProgramRaster(mRSC->getDefaultProgramRaster());
  526. mRSC->setProgramFragment(mFontShaderF.get());
  527. mRSC->setProgramStore(mFontProgramStore.get());
  528. if (mConstantsDirty) {
  529. mFontShaderFConstant->data(mRSC, 0, 0, 1, &mConstants, sizeof(mConstants));
  530. mConstantsDirty = false;
  531. }
  532. if (!mRSC->setupCheck()) {
  533. return;
  534. }
  535. mMesh->renderPrimitiveRange(mRSC, 0, 0, mCurrentQuadIndex * 6);
  536. }
  537. void FontState::appendMeshQuad(float x1, float y1, float z1,
  538. float u1, float v1,
  539. float x2, float y2, float z2,
  540. float u2, float v2,
  541. float x3, float y3, float z3,
  542. float u3, float v3,
  543. float x4, float y4, float z4,
  544. float u4, float v4) {
  545. const uint32_t vertsPerQuad = 4;
  546. const uint32_t floatsPerVert = 6;
  547. float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert;
  548. if (x1 > mSurfaceWidth || y1 < 0.0f || x2 < 0 || y4 > mSurfaceHeight) {
  549. return;
  550. }
  551. /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1);
  552. ALOGE("V1 x: %f y: %f z: %f", x2, y2, z2);
  553. ALOGE("V2 x: %f y: %f z: %f", x3, y3, z3);
  554. ALOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/
  555. (*currentPos++) = x1;
  556. (*currentPos++) = y1;
  557. (*currentPos++) = z1;
  558. (*currentPos++) = 0;
  559. (*currentPos++) = u1;
  560. (*currentPos++) = v1;
  561. (*currentPos++) = x2;
  562. (*currentPos++) = y2;
  563. (*currentPos++) = z2;
  564. (*currentPos++) = 0;
  565. (*currentPos++) = u2;
  566. (*currentPos++) = v2;
  567. (*currentPos++) = x3;
  568. (*currentPos++) = y3;
  569. (*currentPos++) = z3;
  570. (*currentPos++) = 0;
  571. (*currentPos++) = u3;
  572. (*currentPos++) = v3;
  573. (*currentPos++) = x4;
  574. (*currentPos++) = y4;
  575. (*currentPos++) = z4;
  576. (*currentPos++) = 0;
  577. (*currentPos++) = u4;
  578. (*currentPos++) = v4;
  579. mCurrentQuadIndex ++;
  580. if (mCurrentQuadIndex == mMaxNumberOfQuads) {
  581. issueDrawCommand();
  582. mCurrentQuadIndex = 0;
  583. }
  584. }
  585. uint32_t FontState::getRemainingCacheCapacity() {
  586. uint32_t remainingCapacity = 0;
  587. uint32_t totalPixels = 0;
  588. for (uint32_t i = 0; i < mCacheLines.size(); i ++) {
  589. remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol);
  590. totalPixels += mCacheLines[i]->mMaxWidth;
  591. }
  592. remainingCapacity = (remainingCapacity * 100) / totalPixels;
  593. return remainingCapacity;
  594. }
  595. void FontState::precacheLatin(Font *font) {
  596. // Remaining capacity is measured in %
  597. uint32_t remainingCapacity = getRemainingCacheCapacity();
  598. uint32_t precacheIdx = 0;
  599. const size_t l = strlen(mLatinPrecache);
  600. while ((remainingCapacity > 25) && (precacheIdx < l)) {
  601. font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]);
  602. remainingCapacity = getRemainingCacheCapacity();
  603. precacheIdx ++;
  604. }
  605. }
  606. void FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y,
  607. uint32_t startIndex, int32_t numGlyphs,
  608. Font::RenderMode mode,
  609. Font::Rect *bounds,
  610. uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) {
  611. checkInit();
  612. // Render code here
  613. Font *currentFont = mRSC->getFont();
  614. if (!currentFont) {
  615. if (!mDefault.get()) {
  616. char fullPath[1024];
  617. const char * root = getenv("ANDROID_ROOT");
  618. rsAssert(strlen(root) < 256);
  619. strlcpy(fullPath, root, sizeof(fullPath));
  620. strlcat(fullPath, "/fonts/Roboto-Regular.ttf", sizeof(fullPath));
  621. fullPath[sizeof(fullPath)-1] = '\0';
  622. mDefault.set(Font::create(mRSC, fullPath, 8, mRSC->getDPI()));
  623. }
  624. currentFont = mDefault.get();
  625. }
  626. if (!currentFont) {
  627. ALOGE("Unable to initialize any fonts");
  628. return;
  629. }
  630. // Cull things that are off the screen
  631. mSurfaceWidth = (float)mRSC->getCurrentSurfaceWidth();
  632. mSurfaceHeight = (float)mRSC->getCurrentSurfaceHeight();
  633. currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs,
  634. mode, bounds, bitmap, bitmapW, bitmapH);
  635. if (mCurrentQuadIndex != 0) {
  636. issueDrawCommand();
  637. mCurrentQuadIndex = 0;
  638. }
  639. }
  640. void FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) {
  641. renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds);
  642. bounds->bottom = - bounds->bottom;
  643. bounds->top = - bounds->top;
  644. }
  645. void FontState::setFontColor(float r, float g, float b, float a) {
  646. mConstants.mFontColor[0] = r;
  647. mConstants.mFontColor[1] = g;
  648. mConstants.mFontColor[2] = b;
  649. mConstants.mFontColor[3] = a;
  650. mConstants.mGamma = 1.0f;
  651. const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f;
  652. if (luminance <= mBlackThreshold) {
  653. mConstants.mGamma = mBlackGamma;
  654. } else if (luminance >= mWhiteThreshold) {
  655. mConstants.mGamma = mWhiteGamma;
  656. }
  657. mConstantsDirty = true;
  658. }
  659. void FontState::getFontColor(float *r, float *g, float *b, float *a) const {
  660. *r = mConstants.mFontColor[0];
  661. *g = mConstants.mFontColor[1];
  662. *b = mConstants.mFontColor[2];
  663. *a = mConstants.mFontColor[3];
  664. }
  665. void FontState::deinit(Context *rsc) {
  666. mInitialized = false;
  667. mFontShaderFConstant.clear();
  668. mMesh.clear();
  669. mFontShaderF.clear();
  670. mFontSampler.clear();
  671. mFontProgramStore.clear();
  672. mTextTexture.clear();
  673. for (uint32_t i = 0; i < mCacheLines.size(); i ++) {
  674. delete mCacheLines[i];
  675. }
  676. mCacheLines.clear();
  677. mDefault.clear();
  678. #ifndef ANDROID_RS_SERIALIZE
  679. if (mLibrary) {
  680. FT_Done_FreeType( mLibrary );
  681. mLibrary = nullptr;
  682. }
  683. #endif //ANDROID_RS_SERIALIZE
  684. }
  685. #ifndef ANDROID_RS_SERIALIZE
  686. bool FontState::CacheTextureLine::fitBitmap(FT_Bitmap_ *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) {
  687. if ((uint32_t)bitmap->rows > mMaxHeight) {
  688. return false;
  689. }
  690. if (mCurrentCol + (uint32_t)bitmap->width < mMaxWidth) {
  691. *retOriginX = mCurrentCol;
  692. *retOriginY = mCurrentRow;
  693. mCurrentCol += bitmap->width;
  694. mDirty = true;
  695. return true;
  696. }
  697. return false;
  698. }
  699. #endif //ANDROID_RS_SERIALIZE
  700. RsFont rsi_FontCreateFromFile(Context *rsc,
  701. char const *name, size_t name_length,
  702. float fontSize, uint32_t dpi) {
  703. Font *newFont = Font::create(rsc, name, fontSize, dpi);
  704. if (newFont) {
  705. newFont->incUserRef();
  706. }
  707. return newFont;
  708. }
  709. RsFont rsi_FontCreateFromMemory(Context *rsc,
  710. char const *name, size_t name_length,
  711. float fontSize, uint32_t dpi,
  712. const void *data, size_t data_length) {
  713. Font *newFont = Font::create(rsc, name, fontSize, dpi, data, data_length);
  714. if (newFont) {
  715. newFont->incUserRef();
  716. }
  717. return newFont;
  718. }
  719. } // namespace renderscript
  720. } // namespace android