Loading libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java +3 −3 Original line number Diff line number Diff line Loading @@ -84,8 +84,6 @@ public class RsRenderStatesRS { private Allocation mTexTransparent; private Allocation mTexChecker; private Allocation mAllocPV; private Mesh mMbyNMesh; private Mesh mTorus; Loading @@ -95,7 +93,6 @@ public class RsRenderStatesRS { Font mFontSerifItalic; Font mFontSerifBoldItalic; Font mFontMono; private Allocation mTextAlloc; private ScriptC_rsrenderstates mScript; Loading Loading @@ -267,12 +264,15 @@ public class RsRenderStatesRS { mFontSerifBoldItalic = Font.createFromFamily(mRS, mRes, "serif", Font.Style.BOLD_ITALIC, 8); mFontMono = Font.createFromFamily(mRS, mRes, "mono", Font.Style.NORMAL, 8); mTextAlloc = Allocation.createFromString(mRS, "String from allocation"); mScript.set_gFontSans(mFontSans); mScript.set_gFontSerif(mFontSerif); mScript.set_gFontSerifBold(mFontSerifBold); mScript.set_gFontSerifItalic(mFontSerifItalic); mScript.set_gFontSerifBoldItalic(mFontSerifBoldItalic); mScript.set_gFontMono(mFontMono); mScript.set_gTextAlloc(mTextAlloc); } private void initMesh() { Loading libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs +44 −2 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ rs_font gFontSerifBold; rs_font gFontSerifItalic; rs_font gFontSerifBoldItalic; rs_font gFontMono; rs_allocation gTextAlloc; int gDisplayMode; Loading Loading @@ -70,7 +71,7 @@ rs_program_fragment gProgFragmentMultitex; #pragma rs export_var(gProgStoreBlendNoneDepth, gProgStoreBlendNone, gProgStoreBlendAlpha, gProgStoreBlendAdd) #pragma rs export_var(gTexOpaque, gTexTorus, gTexTransparent, gTexChecker) #pragma rs export_var(gMbyNMesh, gTorusMesh) #pragma rs export_var(gFontSans, gFontSerif, gFontSerifBold, gFontSerifItalic, gFontSerifBoldItalic, gFontMono) #pragma rs export_var(gFontSans, gFontSerif, gFontSerifBold, gFontSerifItalic, gFontSerifBoldItalic, gFontMono, gTextAlloc) #pragma rs export_var(gLinearClamp, gLinearWrap, gMipLinearWrap, gMipLinearAniso8, gMipLinearAniso15, gNearestClamp) #pragma rs export_var(gCullBack, gCullFront, gCullNone) #pragma rs export_var(gVSConstants, gFSConstants, gVSInputs, gProgVertexCustom, gProgFragmentCustom, gProgFragmentMultitex) Loading @@ -85,7 +86,7 @@ void init() { void displayFontSamples() { rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); int yPos = 30; int yPos = 100; rsgBindFont(gFontSans); rsgDrawText("Sans font sample", 30, yPos); yPos += 30; Loading @@ -107,6 +108,47 @@ void displayFontSamples() { yPos += 30; rsgBindFont(gFontMono); rsgDrawText("Monospace font sample", 30, yPos); yPos += 50; // Now use text metrics to center the text uint width = rsgGetWidth(); uint height = rsgGetHeight(); int left = 0, right = 0, top = 0, bottom = 0; rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f); rsgBindFont(gFontSerifBoldItalic); rsgMeasureText(gTextAlloc, &left, &right, &top, &bottom); int centeredPos = width / 2 - (right - left) / 2; rsgDrawText(gTextAlloc, centeredPos, yPos); yPos += 30; const char* text = "Centered Text Sample"; rsgMeasureText(text, &left, &right, &top, &bottom); centeredPos = width / 2 - (right - left) / 2; rsgDrawText(text, centeredPos, yPos); yPos += 30; rsgBindFont(gFontSans); text = "More Centered Text Samples"; rsgMeasureText(text, &left, &right, &top, &bottom); centeredPos = width / 2 - (right - left) / 2; rsgDrawText(text, centeredPos, yPos); yPos += 30; // Now draw bottom and top right aligned text text = "Top-right aligned text"; rsgMeasureText(text, &left, &right, &top, &bottom); rsgDrawText(text, width - right, top); text = "Top-left"; rsgMeasureText(text, &left, &right, &top, &bottom); rsgDrawText(text, -left, top); text = "Bottom-right aligned text"; rsgMeasureText(text, &left, &right, &top, &bottom); rsgDrawText(text, width - right, height + bottom); } void bindProgramVertexOrtho() { Loading libs/rs/rsContext.cpp +5 −5 Original line number Diff line number Diff line Loading @@ -258,14 +258,14 @@ void Context::displayDebugStats() sprintf(buffer, "Frame %i ms, Script %i ms", mTimeMSLastFrame, mTimeMSLastScript); float oldR, oldG, oldB, oldA; mStateFont.getFontColor(&oldR, &oldG, &oldB, &oldA); uint32_t bufferLen = strlen(buffer); float shadowCol = 0.2f; float shadowCol = 0.1f; mStateFont.setFontColor(shadowCol, shadowCol, shadowCol, 1.0f); mStateFont.renderText(buffer, 5, getHeight() - 5); mStateFont.renderText(buffer, bufferLen, 5, getHeight() - 5); float textCol = 0.9f; mStateFont.setFontColor(textCol, textCol, textCol, 1.0f); mStateFont.renderText(buffer, 4, getHeight() - 6); mStateFont.setFontColor(1.0f, 0.7f, 0.0f, 1.0f); mStateFont.renderText(buffer, bufferLen, 4, getHeight() - 6); mStateFont.setFontColor(oldR, oldG, oldB, oldA); } Loading libs/rs/rsFont.cpp +104 −52 Original line number Diff line number Diff line Loading @@ -84,34 +84,95 @@ void Font::invalidateTextureCache() } } void Font::drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y) void Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y) { FontState *state = &mRSC->mStateFont; int nPenX = x + glyph->mBitmapLeft; int nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; int32_t nPenX = x + glyph->mBitmapLeft; int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; state->appendMeshQuad(nPenX, nPenY, 0, glyph->mBitmapMinU, glyph->mBitmapMaxV, float u1 = glyph->mBitmapMinU; float u2 = glyph->mBitmapMaxU; float v1 = glyph->mBitmapMinV; float v2 = glyph->mBitmapMaxV; nPenX + (int)glyph->mBitmapWidth, nPenY, 0, glyph->mBitmapMaxU, glyph->mBitmapMaxV, int32_t width = (int32_t) glyph->mBitmapWidth; int32_t height = (int32_t) glyph->mBitmapHeight; nPenX + (int)glyph->mBitmapWidth, nPenY - (int)glyph->mBitmapHeight, 0, glyph->mBitmapMaxU, glyph->mBitmapMinV, state->appendMeshQuad(nPenX, nPenY, 0, u1, v2, nPenX + width, nPenY, 0, u2, v2, nPenX + width, nPenY - height, 0, u2, v1, nPenX, nPenY - height, 0, u1, v1); } void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y, uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) { int32_t nPenX = x + glyph->mBitmapLeft; int32_t nPenY = y + glyph->mBitmapTop; uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth; uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight; FontState *state = &mRSC->mStateFont; uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); const uint8_t* cacheBuffer = state->getTextTextureData(); uint32_t cacheX = 0, cacheY = 0; int32_t bX = 0, bY = 0; for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) { for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) { if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) { LOGE("Skipping invalid index"); continue; } uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; bitmap[bY * bitmapW + bX] = tempCol; } } nPenX, nPenY - (int)glyph->mBitmapHeight, 0, glyph->mBitmapMinU, glyph->mBitmapMinV); } void Font::renderUTF(const char *text, uint32_t len, uint32_t start, int numGlyphs, int x, int y) void Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) { int32_t nPenX = x + glyph->mBitmapLeft; int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; int32_t width = (int32_t) glyph->mBitmapWidth; int32_t height = (int32_t) glyph->mBitmapHeight; if (bounds->bottom > nPenY) { bounds->bottom = nPenY; } if (bounds->left > nPenX) { bounds->left = nPenX; } if (bounds->right < nPenX + width) { bounds->right = nPenX + width; } if (bounds->top < nPenY + height) { bounds->top = nPenY + height; } } void Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, uint32_t start, int32_t numGlyphs, RenderMode mode, Rect *bounds, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { if(!mInitialized || numGlyphs == 0 || text == NULL || len == 0) { return; } int penX = x, penY = y; int glyphsLeft = 1; if(mode == Font::MEASURE) { if (bounds == NULL) { LOGE("No return rectangle provided to measure text"); return; } // Reset min and max of the bounding box to something large bounds->set(1e6, -1e6, -1e6, 1e6); } int32_t penX = x, penY = y; int32_t glyphsLeft = 1; if(numGlyphs > 0) { glyphsLeft = numGlyphs; } Loading @@ -135,7 +196,17 @@ void Font::renderUTF(const char *text, uint32_t len, uint32_t start, int numGlyp // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage if(cachedGlyph->mIsValid) { switch(mode) { case FRAMEBUFFER: drawCachedGlyph(cachedGlyph, penX, penY); break; case BITMAP: drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); break; case MEASURE: measureCachedGlyph(cachedGlyph, penX, penY, bounds); break; } } penX += (cachedGlyph->mAdvance.x >> 6); Loading Loading @@ -283,7 +354,7 @@ FontState::FontState() } // Get the black gamma threshold int blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) { LOGD(" Setting text black gamma threshold to %s", property); blackThreshold = atoi(property); Loading @@ -294,7 +365,7 @@ FontState::FontState() mBlackThreshold = (float)(blackThreshold) / 255.0f; // Get the white gamma threshold int whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) { LOGD(" Setting text white gamma threshold to %s", property); whiteThreshold = atoi(property); Loading Loading @@ -397,13 +468,13 @@ bool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *r uint32_t cacheWidth = getCacheTextureType()->getDimX(); unsigned char *cacheBuffer = (unsigned char*)mTextTexture->getPtr(); unsigned char *bitmapBuffer = bitmap->buffer; uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr(); uint8_t *bitmapBuffer = bitmap->buffer; uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; for(cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { for(cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { unsigned char tempCol = bitmapBuffer[bY * bitmap->width + bX]; uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX]; cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; } } Loading Loading @@ -487,7 +558,7 @@ void FontState::initTextTexture() mTextTexture->deferedUploadToTexture(mRSC, false, 0); // Split up our cache texture into lines of certain widths int nextLine = 0; int32_t nextLine = 0; mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); nextLine += mCacheLines.top()->mMaxHeight; mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); Loading Loading @@ -519,8 +590,8 @@ void FontState::initVertexArrayBuffers() // Four verts, two triangles , six indices per quad for(uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { int i6 = i * 6; int i4 = i * 4; int32_t i6 = i * 6; int32_t i4 = i * 4; indexPtr[i6 + 0] = i4 + 0; indexPtr[i6 + 1] = i4 + 1; Loading Loading @@ -713,7 +784,11 @@ void FontState::precacheLatin(Font *font) { } void FontState::renderText(const char *text, uint32_t len, uint32_t startIndex, int numGlyphs, int x, int y) void FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y, uint32_t startIndex, int32_t numGlyphs, Font::RenderMode mode, Font::Rect *bounds, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { checkInit(); Loading @@ -730,7 +805,8 @@ void FontState::renderText(const char *text, uint32_t len, uint32_t startIndex, return; } currentFont->renderUTF(text, len, startIndex, numGlyphs, x, y); currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs, mode, bounds, bitmap, bitmapW, bitmapH); if(mCurrentQuadIndex != 0) { issueDrawCommand(); Loading @@ -738,32 +814,8 @@ void FontState::renderText(const char *text, uint32_t len, uint32_t startIndex, } } void FontState::renderText(const char *text, int x, int y) { size_t textLen = strlen(text); renderText(text, textLen, 0, -1, x, y); } void FontState::renderText(Allocation *alloc, int x, int y) { if(!alloc) { return; } const char *text = (const char *)alloc->getPtr(); size_t allocSize = alloc->getType()->getSizeBytes(); renderText(text, allocSize, 0, -1, x, y); } void FontState::renderText(Allocation *alloc, uint32_t start, int len, int x, int y) { if(!alloc) { return; } const char *text = (const char *)alloc->getPtr(); size_t allocSize = alloc->getType()->getSizeBytes(); renderText(text, allocSize, start, len, x, y); void FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) { renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds); } void FontState::setFontColor(float r, float g, float b, float a) { Loading @@ -773,7 +825,7 @@ void FontState::setFontColor(float r, float g, float b, float a) { mConstants.mFontColor[3] = a; mConstants.mGamma = 1.0f; const int luminance = (r * 2.0f + g * 5.0f + b) / 8.0f; const int32_t luminance = (r * 2.0f + g * 5.0f + b) / 8.0f; if (luminance <= mBlackThreshold) { mConstants.mGamma = mBlackGamma; } else if (luminance >= mWhiteThreshold) { Loading libs/rs/rsFont.h +41 −10 Original line number Diff line number Diff line Loading @@ -45,12 +45,26 @@ class FontState; class Font : public ObjectBase { public: ~Font(); enum RenderMode { FRAMEBUFFER, BITMAP, MEASURE, }; // Pointer to the utf data, length of data, where to start, number of glyphs ot read // (each glyph may be longer than a char because we are dealing with utf data) // Last two variables are the initial pen position void renderUTF(const char *text, uint32_t len, uint32_t start, int numGlyphs, int x, int y); struct Rect { int32_t left; int32_t top; int32_t right; int32_t bottom; void set(int32_t l, int32_t r, int32_t t, int32_t b) { left = l; right = r; top = t; bottom = b; } }; ~Font(); // Currently files do not get serialized, // but we need to inherit from ObjectBase for ref tracking Loading @@ -66,6 +80,14 @@ protected: friend class FontState; // Pointer to the utf data, length of data, where to start, number of glyphs ot read // (each glyph may be longer than a char because we are dealing with utf data) // Last two variables are the initial pen position void renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, uint32_t start, int32_t numGlyphs, RenderMode mode = FRAMEBUFFER, Rect *bounds = NULL, uint8_t *bitmap = NULL, uint32_t bitmapW = 0, uint32_t bitmapH = 0); void invalidateTextureCache(); struct CachedGlyphInfo { Loading Loading @@ -106,7 +128,10 @@ protected: CachedGlyphInfo *cacheGlyph(uint32_t glyph); void updateGlyphCache(CachedGlyphInfo *glyph); void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y); void measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds); void drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y); void drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH); }; class FontState Loading @@ -121,10 +146,13 @@ public: ObjectBaseRef<Font> mDefault; ObjectBaseRef<Font> mLast; void renderText(const char *text, uint32_t len, uint32_t startIndex, int numGlyphs, int x, int y); void renderText(const char *text, int x, int y); void renderText(Allocation *alloc, int x, int y); void renderText(Allocation *alloc, uint32_t start, int len, int x, int y); void renderText(const char *text, uint32_t len, int32_t x, int32_t y, uint32_t startIndex = 0, int numGlyphs = -1, Font::RenderMode mode = Font::FRAMEBUFFER, Font::Rect *bounds = NULL, uint8_t *bitmap = NULL, uint32_t bitmapW = 0, uint32_t bitmapH = 0); void measureText(const char *text, uint32_t len, Font::Rect *bounds); void setFontColor(float r, float g, float b, float a); void getFontColor(float *r, float *g, float *b, float *a) const; Loading Loading @@ -198,6 +226,9 @@ protected: // Texture to cache glyph bitmaps ObjectBaseRef<Allocation> mTextTexture; void initTextTexture(); const uint8_t* getTextTextureData() const { return (uint8_t*)mTextTexture->getPtr(); } bool cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY); const Type* getCacheTextureType() { Loading Loading
libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java +3 −3 Original line number Diff line number Diff line Loading @@ -84,8 +84,6 @@ public class RsRenderStatesRS { private Allocation mTexTransparent; private Allocation mTexChecker; private Allocation mAllocPV; private Mesh mMbyNMesh; private Mesh mTorus; Loading @@ -95,7 +93,6 @@ public class RsRenderStatesRS { Font mFontSerifItalic; Font mFontSerifBoldItalic; Font mFontMono; private Allocation mTextAlloc; private ScriptC_rsrenderstates mScript; Loading Loading @@ -267,12 +264,15 @@ public class RsRenderStatesRS { mFontSerifBoldItalic = Font.createFromFamily(mRS, mRes, "serif", Font.Style.BOLD_ITALIC, 8); mFontMono = Font.createFromFamily(mRS, mRes, "mono", Font.Style.NORMAL, 8); mTextAlloc = Allocation.createFromString(mRS, "String from allocation"); mScript.set_gFontSans(mFontSans); mScript.set_gFontSerif(mFontSerif); mScript.set_gFontSerifBold(mFontSerifBold); mScript.set_gFontSerifItalic(mFontSerifItalic); mScript.set_gFontSerifBoldItalic(mFontSerifBoldItalic); mScript.set_gFontMono(mFontMono); mScript.set_gTextAlloc(mTextAlloc); } private void initMesh() { Loading
libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs +44 −2 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ rs_font gFontSerifBold; rs_font gFontSerifItalic; rs_font gFontSerifBoldItalic; rs_font gFontMono; rs_allocation gTextAlloc; int gDisplayMode; Loading Loading @@ -70,7 +71,7 @@ rs_program_fragment gProgFragmentMultitex; #pragma rs export_var(gProgStoreBlendNoneDepth, gProgStoreBlendNone, gProgStoreBlendAlpha, gProgStoreBlendAdd) #pragma rs export_var(gTexOpaque, gTexTorus, gTexTransparent, gTexChecker) #pragma rs export_var(gMbyNMesh, gTorusMesh) #pragma rs export_var(gFontSans, gFontSerif, gFontSerifBold, gFontSerifItalic, gFontSerifBoldItalic, gFontMono) #pragma rs export_var(gFontSans, gFontSerif, gFontSerifBold, gFontSerifItalic, gFontSerifBoldItalic, gFontMono, gTextAlloc) #pragma rs export_var(gLinearClamp, gLinearWrap, gMipLinearWrap, gMipLinearAniso8, gMipLinearAniso15, gNearestClamp) #pragma rs export_var(gCullBack, gCullFront, gCullNone) #pragma rs export_var(gVSConstants, gFSConstants, gVSInputs, gProgVertexCustom, gProgFragmentCustom, gProgFragmentMultitex) Loading @@ -85,7 +86,7 @@ void init() { void displayFontSamples() { rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); int yPos = 30; int yPos = 100; rsgBindFont(gFontSans); rsgDrawText("Sans font sample", 30, yPos); yPos += 30; Loading @@ -107,6 +108,47 @@ void displayFontSamples() { yPos += 30; rsgBindFont(gFontMono); rsgDrawText("Monospace font sample", 30, yPos); yPos += 50; // Now use text metrics to center the text uint width = rsgGetWidth(); uint height = rsgGetHeight(); int left = 0, right = 0, top = 0, bottom = 0; rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f); rsgBindFont(gFontSerifBoldItalic); rsgMeasureText(gTextAlloc, &left, &right, &top, &bottom); int centeredPos = width / 2 - (right - left) / 2; rsgDrawText(gTextAlloc, centeredPos, yPos); yPos += 30; const char* text = "Centered Text Sample"; rsgMeasureText(text, &left, &right, &top, &bottom); centeredPos = width / 2 - (right - left) / 2; rsgDrawText(text, centeredPos, yPos); yPos += 30; rsgBindFont(gFontSans); text = "More Centered Text Samples"; rsgMeasureText(text, &left, &right, &top, &bottom); centeredPos = width / 2 - (right - left) / 2; rsgDrawText(text, centeredPos, yPos); yPos += 30; // Now draw bottom and top right aligned text text = "Top-right aligned text"; rsgMeasureText(text, &left, &right, &top, &bottom); rsgDrawText(text, width - right, top); text = "Top-left"; rsgMeasureText(text, &left, &right, &top, &bottom); rsgDrawText(text, -left, top); text = "Bottom-right aligned text"; rsgMeasureText(text, &left, &right, &top, &bottom); rsgDrawText(text, width - right, height + bottom); } void bindProgramVertexOrtho() { Loading
libs/rs/rsContext.cpp +5 −5 Original line number Diff line number Diff line Loading @@ -258,14 +258,14 @@ void Context::displayDebugStats() sprintf(buffer, "Frame %i ms, Script %i ms", mTimeMSLastFrame, mTimeMSLastScript); float oldR, oldG, oldB, oldA; mStateFont.getFontColor(&oldR, &oldG, &oldB, &oldA); uint32_t bufferLen = strlen(buffer); float shadowCol = 0.2f; float shadowCol = 0.1f; mStateFont.setFontColor(shadowCol, shadowCol, shadowCol, 1.0f); mStateFont.renderText(buffer, 5, getHeight() - 5); mStateFont.renderText(buffer, bufferLen, 5, getHeight() - 5); float textCol = 0.9f; mStateFont.setFontColor(textCol, textCol, textCol, 1.0f); mStateFont.renderText(buffer, 4, getHeight() - 6); mStateFont.setFontColor(1.0f, 0.7f, 0.0f, 1.0f); mStateFont.renderText(buffer, bufferLen, 4, getHeight() - 6); mStateFont.setFontColor(oldR, oldG, oldB, oldA); } Loading
libs/rs/rsFont.cpp +104 −52 Original line number Diff line number Diff line Loading @@ -84,34 +84,95 @@ void Font::invalidateTextureCache() } } void Font::drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y) void Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y) { FontState *state = &mRSC->mStateFont; int nPenX = x + glyph->mBitmapLeft; int nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; int32_t nPenX = x + glyph->mBitmapLeft; int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; state->appendMeshQuad(nPenX, nPenY, 0, glyph->mBitmapMinU, glyph->mBitmapMaxV, float u1 = glyph->mBitmapMinU; float u2 = glyph->mBitmapMaxU; float v1 = glyph->mBitmapMinV; float v2 = glyph->mBitmapMaxV; nPenX + (int)glyph->mBitmapWidth, nPenY, 0, glyph->mBitmapMaxU, glyph->mBitmapMaxV, int32_t width = (int32_t) glyph->mBitmapWidth; int32_t height = (int32_t) glyph->mBitmapHeight; nPenX + (int)glyph->mBitmapWidth, nPenY - (int)glyph->mBitmapHeight, 0, glyph->mBitmapMaxU, glyph->mBitmapMinV, state->appendMeshQuad(nPenX, nPenY, 0, u1, v2, nPenX + width, nPenY, 0, u2, v2, nPenX + width, nPenY - height, 0, u2, v1, nPenX, nPenY - height, 0, u1, v1); } void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y, uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) { int32_t nPenX = x + glyph->mBitmapLeft; int32_t nPenY = y + glyph->mBitmapTop; uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth; uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight; FontState *state = &mRSC->mStateFont; uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); const uint8_t* cacheBuffer = state->getTextTextureData(); uint32_t cacheX = 0, cacheY = 0; int32_t bX = 0, bY = 0; for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) { for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) { if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) { LOGE("Skipping invalid index"); continue; } uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; bitmap[bY * bitmapW + bX] = tempCol; } } nPenX, nPenY - (int)glyph->mBitmapHeight, 0, glyph->mBitmapMinU, glyph->mBitmapMinV); } void Font::renderUTF(const char *text, uint32_t len, uint32_t start, int numGlyphs, int x, int y) void Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) { int32_t nPenX = x + glyph->mBitmapLeft; int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; int32_t width = (int32_t) glyph->mBitmapWidth; int32_t height = (int32_t) glyph->mBitmapHeight; if (bounds->bottom > nPenY) { bounds->bottom = nPenY; } if (bounds->left > nPenX) { bounds->left = nPenX; } if (bounds->right < nPenX + width) { bounds->right = nPenX + width; } if (bounds->top < nPenY + height) { bounds->top = nPenY + height; } } void Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, uint32_t start, int32_t numGlyphs, RenderMode mode, Rect *bounds, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { if(!mInitialized || numGlyphs == 0 || text == NULL || len == 0) { return; } int penX = x, penY = y; int glyphsLeft = 1; if(mode == Font::MEASURE) { if (bounds == NULL) { LOGE("No return rectangle provided to measure text"); return; } // Reset min and max of the bounding box to something large bounds->set(1e6, -1e6, -1e6, 1e6); } int32_t penX = x, penY = y; int32_t glyphsLeft = 1; if(numGlyphs > 0) { glyphsLeft = numGlyphs; } Loading @@ -135,7 +196,17 @@ void Font::renderUTF(const char *text, uint32_t len, uint32_t start, int numGlyp // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage if(cachedGlyph->mIsValid) { switch(mode) { case FRAMEBUFFER: drawCachedGlyph(cachedGlyph, penX, penY); break; case BITMAP: drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); break; case MEASURE: measureCachedGlyph(cachedGlyph, penX, penY, bounds); break; } } penX += (cachedGlyph->mAdvance.x >> 6); Loading Loading @@ -283,7 +354,7 @@ FontState::FontState() } // Get the black gamma threshold int blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) { LOGD(" Setting text black gamma threshold to %s", property); blackThreshold = atoi(property); Loading @@ -294,7 +365,7 @@ FontState::FontState() mBlackThreshold = (float)(blackThreshold) / 255.0f; // Get the white gamma threshold int whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) { LOGD(" Setting text white gamma threshold to %s", property); whiteThreshold = atoi(property); Loading Loading @@ -397,13 +468,13 @@ bool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *r uint32_t cacheWidth = getCacheTextureType()->getDimX(); unsigned char *cacheBuffer = (unsigned char*)mTextTexture->getPtr(); unsigned char *bitmapBuffer = bitmap->buffer; uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr(); uint8_t *bitmapBuffer = bitmap->buffer; uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; for(cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { for(cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { unsigned char tempCol = bitmapBuffer[bY * bitmap->width + bX]; uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX]; cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; } } Loading Loading @@ -487,7 +558,7 @@ void FontState::initTextTexture() mTextTexture->deferedUploadToTexture(mRSC, false, 0); // Split up our cache texture into lines of certain widths int nextLine = 0; int32_t nextLine = 0; mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); nextLine += mCacheLines.top()->mMaxHeight; mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); Loading Loading @@ -519,8 +590,8 @@ void FontState::initVertexArrayBuffers() // Four verts, two triangles , six indices per quad for(uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { int i6 = i * 6; int i4 = i * 4; int32_t i6 = i * 6; int32_t i4 = i * 4; indexPtr[i6 + 0] = i4 + 0; indexPtr[i6 + 1] = i4 + 1; Loading Loading @@ -713,7 +784,11 @@ void FontState::precacheLatin(Font *font) { } void FontState::renderText(const char *text, uint32_t len, uint32_t startIndex, int numGlyphs, int x, int y) void FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y, uint32_t startIndex, int32_t numGlyphs, Font::RenderMode mode, Font::Rect *bounds, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { checkInit(); Loading @@ -730,7 +805,8 @@ void FontState::renderText(const char *text, uint32_t len, uint32_t startIndex, return; } currentFont->renderUTF(text, len, startIndex, numGlyphs, x, y); currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs, mode, bounds, bitmap, bitmapW, bitmapH); if(mCurrentQuadIndex != 0) { issueDrawCommand(); Loading @@ -738,32 +814,8 @@ void FontState::renderText(const char *text, uint32_t len, uint32_t startIndex, } } void FontState::renderText(const char *text, int x, int y) { size_t textLen = strlen(text); renderText(text, textLen, 0, -1, x, y); } void FontState::renderText(Allocation *alloc, int x, int y) { if(!alloc) { return; } const char *text = (const char *)alloc->getPtr(); size_t allocSize = alloc->getType()->getSizeBytes(); renderText(text, allocSize, 0, -1, x, y); } void FontState::renderText(Allocation *alloc, uint32_t start, int len, int x, int y) { if(!alloc) { return; } const char *text = (const char *)alloc->getPtr(); size_t allocSize = alloc->getType()->getSizeBytes(); renderText(text, allocSize, start, len, x, y); void FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) { renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds); } void FontState::setFontColor(float r, float g, float b, float a) { Loading @@ -773,7 +825,7 @@ void FontState::setFontColor(float r, float g, float b, float a) { mConstants.mFontColor[3] = a; mConstants.mGamma = 1.0f; const int luminance = (r * 2.0f + g * 5.0f + b) / 8.0f; const int32_t luminance = (r * 2.0f + g * 5.0f + b) / 8.0f; if (luminance <= mBlackThreshold) { mConstants.mGamma = mBlackGamma; } else if (luminance >= mWhiteThreshold) { Loading
libs/rs/rsFont.h +41 −10 Original line number Diff line number Diff line Loading @@ -45,12 +45,26 @@ class FontState; class Font : public ObjectBase { public: ~Font(); enum RenderMode { FRAMEBUFFER, BITMAP, MEASURE, }; // Pointer to the utf data, length of data, where to start, number of glyphs ot read // (each glyph may be longer than a char because we are dealing with utf data) // Last two variables are the initial pen position void renderUTF(const char *text, uint32_t len, uint32_t start, int numGlyphs, int x, int y); struct Rect { int32_t left; int32_t top; int32_t right; int32_t bottom; void set(int32_t l, int32_t r, int32_t t, int32_t b) { left = l; right = r; top = t; bottom = b; } }; ~Font(); // Currently files do not get serialized, // but we need to inherit from ObjectBase for ref tracking Loading @@ -66,6 +80,14 @@ protected: friend class FontState; // Pointer to the utf data, length of data, where to start, number of glyphs ot read // (each glyph may be longer than a char because we are dealing with utf data) // Last two variables are the initial pen position void renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, uint32_t start, int32_t numGlyphs, RenderMode mode = FRAMEBUFFER, Rect *bounds = NULL, uint8_t *bitmap = NULL, uint32_t bitmapW = 0, uint32_t bitmapH = 0); void invalidateTextureCache(); struct CachedGlyphInfo { Loading Loading @@ -106,7 +128,10 @@ protected: CachedGlyphInfo *cacheGlyph(uint32_t glyph); void updateGlyphCache(CachedGlyphInfo *glyph); void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y); void measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds); void drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y); void drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH); }; class FontState Loading @@ -121,10 +146,13 @@ public: ObjectBaseRef<Font> mDefault; ObjectBaseRef<Font> mLast; void renderText(const char *text, uint32_t len, uint32_t startIndex, int numGlyphs, int x, int y); void renderText(const char *text, int x, int y); void renderText(Allocation *alloc, int x, int y); void renderText(Allocation *alloc, uint32_t start, int len, int x, int y); void renderText(const char *text, uint32_t len, int32_t x, int32_t y, uint32_t startIndex = 0, int numGlyphs = -1, Font::RenderMode mode = Font::FRAMEBUFFER, Font::Rect *bounds = NULL, uint8_t *bitmap = NULL, uint32_t bitmapW = 0, uint32_t bitmapH = 0); void measureText(const char *text, uint32_t len, Font::Rect *bounds); void setFontColor(float r, float g, float b, float a); void getFontColor(float *r, float *g, float *b, float *a) const; Loading Loading @@ -198,6 +226,9 @@ protected: // Texture to cache glyph bitmaps ObjectBaseRef<Allocation> mTextTexture; void initTextTexture(); const uint8_t* getTextTextureData() const { return (uint8_t*)mTextTexture->getPtr(); } bool cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY); const Type* getCacheTextureType() { Loading