diff options
Diffstat (limited to 'src/engine/client/text.cpp')
| -rw-r--r-- | src/engine/client/text.cpp | 160 |
1 files changed, 80 insertions, 80 deletions
diff --git a/src/engine/client/text.cpp b/src/engine/client/text.cpp index da91980d..b0896b92 100644 --- a/src/engine/client/text.cpp +++ b/src/engine/client/text.cpp @@ -36,7 +36,7 @@ static int aFontSizes[] = {8,9,10,11,12,13,14,15,16,17,18,19,20,36,64}; struct CFontChar { int m_ID; - + // these values are scaled to the pFont size // width * font_size == real_size float m_Width; @@ -44,7 +44,7 @@ struct CFontChar float m_OffsetX; float m_OffsetY; float m_AdvanceX; - + float m_aUvs[4]; int64 m_TouchTime; }; @@ -57,16 +57,16 @@ struct CFontSizeData GLuint m_aTextures[2]; int m_TextureWidth; int m_TextureHeight; - + int m_NumXChars; int m_NumYChars; - + int m_CharMaxWidth; int m_CharMaxHeight; - + CFontChar m_aCharacters[MAX_CHARACTERS*MAX_CHARACTERS]; - - int m_CurrentCharacter; + + int m_CurrentCharacter; }; class CFont @@ -82,7 +82,7 @@ class CTextRender : public IEngineTextRender { IGraphics *m_pGraphics; IGraphics *Graphics() { return m_pGraphics; } - + int WordLength(const char *pText) { int s = 1; @@ -106,13 +106,13 @@ class CTextRender : public IEngineTextRender float m_TextOutlineG; float m_TextOutlineB; float m_TextOutlineA; - + int m_FontTextureFormat; CFont *m_pDefaultFont; FT_Library m_FTLibrary; - + int GetFontSizeIndex(int Pixelsize) { for(unsigned i = 0; i < NUM_FONT_SIZES; i++) @@ -120,18 +120,18 @@ class CTextRender : public IEngineTextRender if(aFontSizes[i] >= Pixelsize) return i; } - + return NUM_FONT_SIZES-1; } - + void Grow(unsigned char *pIn, unsigned char *pOut, int w, int h) { - for(int y = 0; y < h; y++) - for(int x = 0; x < w; x++) - { - int c = pIn[y*w+x]; + for(int y = 0; y < h; y++) + for(int x = 0; x < w; x++) + { + int c = pIn[y*w+x]; for(int sy = -1; sy <= 1; sy++) for(int sx = -1; sx <= 1; sx++) @@ -142,7 +142,7 @@ class CTextRender : public IEngineTextRender { int Index = GetY*w+GetX; if(pIn[Index] > c) - c = pIn[Index]; + c = pIn[Index]; } } @@ -157,18 +157,18 @@ class CTextRender : public IEngineTextRender int Height = CharHeight*Ychars; void *pMem = mem_alloc(Width*Height, 1); mem_zero(pMem, Width*Height); - + if(pSizeData->m_aTextures[0] == 0) glGenTextures(2, pSizeData->m_aTextures); else FontMemoryUsage -= pSizeData->m_TextureWidth*pSizeData->m_TextureHeight*2; - + pSizeData->m_NumXChars = Xchars; pSizeData->m_NumYChars = Ychars; pSizeData->m_TextureWidth = Width; pSizeData->m_TextureHeight = Height; pSizeData->m_CurrentCharacter = 0; - + for(int i = 0; i < 2; i++) { glBindTexture(GL_TEXTURE_2D, pSizeData->m_aTextures[i]); @@ -177,9 +177,9 @@ class CTextRender : public IEngineTextRender glTexImage2D(GL_TEXTURE_2D, 0, m_FontTextureFormat, Width, Height, 0, m_FontTextureFormat, GL_UNSIGNED_BYTE, pMem); FontMemoryUsage += Width*Height; } - + dbg_msg("", "pFont memory usage: %d", FontMemoryUsage); - + mem_free(pMem); } @@ -198,43 +198,43 @@ class CTextRender : public IEngineTextRender pSizeData->m_NumXChars <<= 1; else pSizeData->m_NumYChars <<= 1; - InitTexture(pSizeData, pSizeData->m_CharMaxWidth, pSizeData->m_CharMaxHeight, pSizeData->m_NumXChars, pSizeData->m_NumYChars); + InitTexture(pSizeData, pSizeData->m_CharMaxWidth, pSizeData->m_CharMaxHeight, pSizeData->m_NumXChars, pSizeData->m_NumYChars); } - - + + // TODO: Refactor: move this into a pFont class void InitIndex(CFont *pFont, int Index) { CFontSizeData *pSizeData = &pFont->m_aSizes[Index]; - + pSizeData->m_FontSize = aFontSizes[Index]; FT_Set_Pixel_Sizes(pFont->m_FtFace, 0, pSizeData->m_FontSize); - + int OutlineThickness = AdjustOutlineThicknessToFontSize(1, pSizeData->m_FontSize); - + { unsigned GlyphIndex; int MaxH = 0; int MaxW = 0; - + int Charcode = FT_Get_First_Char(pFont->m_FtFace, &GlyphIndex); while(GlyphIndex != 0) - { + { // do stuff FT_Load_Glyph(pFont->m_FtFace, GlyphIndex, FT_LOAD_DEFAULT); - + if(pFont->m_FtFace->glyph->metrics.width > MaxW) MaxW = pFont->m_FtFace->glyph->metrics.width; // ignore_convention if(pFont->m_FtFace->glyph->metrics.height > MaxH) MaxH = pFont->m_FtFace->glyph->metrics.height; // ignore_convention Charcode = FT_Get_Next_Char(pFont->m_FtFace, Charcode, &GlyphIndex); } - + MaxW = (MaxW>>6)+2+OutlineThickness*2; MaxH = (MaxH>>6)+2+OutlineThickness*2; - + for(pSizeData->m_CharMaxWidth = 1; pSizeData->m_CharMaxWidth < MaxW; pSizeData->m_CharMaxWidth <<= 1); for(pSizeData->m_CharMaxHeight = 1; pSizeData->m_CharMaxHeight < MaxH; pSizeData->m_CharMaxHeight <<= 1); } - + //dbg_msg("pFont", "init size %d, texture size %d %d", pFont->sizes[index].font_size, w, h); //FT_New_Face(m_FTLibrary, "data/fonts/vera.ttf", 0, &pFont->ft_face); InitTexture(pSizeData, pSizeData->m_CharMaxWidth, pSizeData->m_CharMaxHeight, 8, 8); @@ -253,7 +253,7 @@ class CTextRender : public IEngineTextRender { int x = (SlotID%pSizeData->m_NumXChars) * (pSizeData->m_TextureWidth/pSizeData->m_NumXChars); int y = (SlotID/pSizeData->m_NumXChars) * (pSizeData->m_TextureHeight/pSizeData->m_NumYChars); - + glBindTexture(GL_TEXTURE_2D, pSizeData->m_aTextures[Texnum]); glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, pSizeData->m_TextureWidth/pSizeData->m_NumXChars, @@ -284,13 +284,13 @@ class CTextRender : public IEngineTextRender if(pSizeData->m_aCharacters[i].m_TouchTime < pSizeData->m_aCharacters[Oldest].m_TouchTime) Oldest = i; } - + if(time_get()-pSizeData->m_aCharacters[Oldest].m_TouchTime < time_freq()) { IncreaseTextureSize(pSizeData); return GetSlot(pSizeData); } - + return Oldest; } } @@ -315,12 +315,12 @@ class CTextRender : public IEngineTextRender } pBitmap = &pFont->m_FtFace->glyph->bitmap; // ignore_convention - + // fetch slot SlotID = GetSlot(pSizeData); if(SlotID < 0) return -1; - + // adjust spacing int OutlineThickness = AdjustOutlineThicknessToFontSize(1, pSizeData->m_FontSize); x += OutlineThickness; @@ -337,7 +337,7 @@ class CTextRender : public IEngineTextRender } else if(pBitmap->pixel_mode == FT_PIXEL_MODE_MONO) // ignore_convention { - for(py = 0; py < pBitmap->rows; py++) // ignore_convention + for(py = 0; py < pBitmap->rows; py++) // ignore_convention for(px = 0; px < pBitmap->width; px++) // ignore_convention { if(pBitmap->buffer[py*pBitmap->pitch+px/8]&(1<<(7-(px%8)))) // ignore_convention @@ -345,13 +345,13 @@ class CTextRender : public IEngineTextRender } } - if(0) for(py = 0; py < SlotW; py++) - for(px = 0; px < SlotH; px++) + if(0) for(py = 0; py < SlotW; py++) + for(px = 0; px < SlotH; px++) ms_aGlyphData[py*SlotW+px] = 255; - + // upload the glyph UploadGlyph(pSizeData, 0, SlotID, Chr, ms_aGlyphData); - + if(OutlineThickness == 1) { Grow(ms_aGlyphData, ms_aGlyphDataOutlined, SlotW, SlotH); @@ -366,7 +366,7 @@ class CTextRender : public IEngineTextRender } UploadGlyph(pSizeData, 1, SlotID, Chr, ms_aGlyphData); } - + // set char info { CFontChar *pFontchr = &pSizeData->m_aCharacters[SlotID]; @@ -375,27 +375,27 @@ class CTextRender : public IEngineTextRender float Vscale = 1.0f/pSizeData->m_TextureHeight; int Height = pBitmap->rows + OutlineThickness*2 + 2; // ignore_convention int Width = pBitmap->width + OutlineThickness*2 + 2; // ignore_convention - + pFontchr->m_ID = Chr; pFontchr->m_Height = Height * Scale; pFontchr->m_Width = Width * Scale; pFontchr->m_OffsetX = (pFont->m_FtFace->glyph->bitmap_left-1) * Scale; // ignore_convention pFontchr->m_OffsetY = (pSizeData->m_FontSize - pFont->m_FtFace->glyph->bitmap_top) * Scale; // ignore_convention pFontchr->m_AdvanceX = (pFont->m_FtFace->glyph->advance.x>>6) * Scale; // ignore_convention - + pFontchr->m_aUvs[0] = (SlotID%pSizeData->m_NumXChars) / (float)(pSizeData->m_NumXChars); pFontchr->m_aUvs[1] = (SlotID/pSizeData->m_NumXChars) / (float)(pSizeData->m_NumYChars); pFontchr->m_aUvs[2] = pFontchr->m_aUvs[0] + Width*Uscale; pFontchr->m_aUvs[3] = pFontchr->m_aUvs[1] + Height*Vscale; } - + return SlotID; } CFontChar *GetChar(CFont *pFont, CFontSizeData *pSizeData, int Chr) { CFontChar *pFontchr = NULL; - + // search for the character // TODO: remove this linear search int i; @@ -407,7 +407,7 @@ class CTextRender : public IEngineTextRender break; } } - + // check if we need to render the character if(!pFontchr) { @@ -415,12 +415,12 @@ class CTextRender : public IEngineTextRender if(Index >= 0) pFontchr = &pSizeData->m_aCharacters[Index]; } - + // touch the character // TODO: don't call time_get here if(pFontchr) pFontchr->m_TouchTime = time_get(); - + return pFontchr; } @@ -436,8 +436,8 @@ class CTextRender : public IEngineTextRender FT_Get_Kerning(pFont->m_FtFace, Left, Right, FT_KERNING_DEFAULT, &Kerning); return (Kerning.x>>6); } - - + + public: CTextRender() { @@ -457,21 +457,21 @@ public: // GL_LUMINANCE can be good for debugging m_FontTextureFormat = GL_ALPHA; } - + virtual void Init() { m_pGraphics = Kernel()->RequestInterface<IGraphics>(); FT_Init_FreeType(&m_FTLibrary); } - + virtual CFont *LoadFont(const char *pFilename) { CFont *pFont = (CFont *)mem_alloc(sizeof(CFont), 1); - + mem_zero(pFont, sizeof(*pFont)); str_copy(pFont->m_aFilename, pFilename, sizeof(pFont->m_aFilename)); - + if(FT_New_Face(m_FTLibrary, pFont->m_aFilename, 0, &pFont->m_FtFace)) { mem_free(pFont); @@ -480,7 +480,7 @@ public: for(unsigned i = 0; i < NUM_FONT_SIZES; i++) pFont->m_aSizes[i].m_FontSize = -1; - + dbg_msg("textrender", "loaded pFont from '%s'", pFilename); return pFont; }; @@ -495,8 +495,8 @@ public: dbg_msg("textrender", "default pFont set %p", pFont); m_pDefaultFont = pFont; } - - + + virtual void SetCursor(CTextCursor *pCursor, float x, float y, float FontSize, int Flags) { mem_zero(pCursor, sizeof(*pCursor)); @@ -510,8 +510,8 @@ public: pCursor->m_Flags = Flags; pCursor->m_CharCount = 0; } - - + + virtual void Text(void *pFontSetV, float x, float y, float Size, const char *pText, int MaxWidth) { CTextCursor Cursor; @@ -527,7 +527,7 @@ public: TextEx(&Cursor, pText, Length); return Cursor.m_X; } - + virtual int TextLineCount(void *pFontSetV, float Size, const char *pText, float LineWidth) { CTextCursor Cursor; @@ -552,12 +552,12 @@ public: m_TextOutlineB = b; m_TextOutlineA = a; } - + virtual void TextEx(CTextCursor *pCursor, const char *pText, int Length) { CFont *pFont = pCursor->m_pFont; CFontSizeData *pSizeData = NULL; - + //dbg_msg("textrender", "rendering text '%s'", text); float ScreenX0, ScreenY0, ScreenX1, ScreenY1; @@ -576,7 +576,7 @@ public: // to correct coords, convert to screen coords, round, and convert back Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1); - + FakeToScreenX = (Graphics()->ScreenWidth()/(ScreenX1-ScreenX0)); FakeToScreenY = (Graphics()->ScreenHeight()/(ScreenY1-ScreenY0)); ActualX = (int)(pCursor->m_X * FakeToScreenX); @@ -592,7 +592,7 @@ public: // fetch pFont data if(!pFont) pFont = m_pDefaultFont; - + if(!pFont) return; @@ -600,11 +600,11 @@ public: RenderSetup(pFont, ActualSize); float Scale = 1/pSizeData->m_FontSize; - + // set length if(Length < 0) Length = str_length(pText); - + pEnd = pText + Length; // if we don't want to render, we can just skip the first outline pass @@ -649,7 +649,7 @@ public: Compare.m_Flags &= ~TEXTFLAG_RENDER; Compare.m_LineWidth = -1; TextEx(&Compare, pText, Wlen); - + if(Compare.m_X-DrawX > pCursor->m_LineWidth) { // word can't be fitted in one line, cut it @@ -659,11 +659,11 @@ public: Cutter.m_Y = DrawY; Cutter.m_Flags &= ~TEXTFLAG_RENDER; Cutter.m_Flags |= TEXTFLAG_STOP_AT_END; - + TextEx(&Cutter, (const char *)pCurrent, Wlen); Wlen = Cutter.m_CharCount; NewLine = 1; - + if(Wlen <= 3) // if we can't place 3 chars of the word on this line, take the next Wlen = 0; } @@ -672,10 +672,10 @@ public: NewLine = 1; Wlen = 0; } - + pBatchEnd = pCurrent + Wlen; } - + const char *pTmp = pCurrent; int NextCharacter = str_utf8_decode(&pTmp); while(pCurrent < pBatchEnd) @@ -683,7 +683,7 @@ public: int Character = NextCharacter; pCurrent = pTmp; NextCharacter = str_utf8_decode(&pTmp); - + if(Character == '\n') { DrawX = pCursor->m_StartX; @@ -718,14 +718,14 @@ public: pCursor->m_CharCount++; } } - + if(NewLine) { DrawX = pCursor->m_StartX; DrawY += Size; GotNewLine = 1; DrawX = (int)(DrawX * FakeToScreenX) / FakeToScreenX; // realign - DrawY = (int)(DrawY * FakeToScreenY) / FakeToScreenY; + DrawY = (int)(DrawY * FakeToScreenY) / FakeToScreenY; ++LineCount; } } @@ -736,11 +736,11 @@ public: pCursor->m_X = DrawX; pCursor->m_LineCount = LineCount; - + if(GotNewLine) pCursor->m_Y = DrawY; } - + }; IEngineTextRender *CreateEngineTextRender() { return new CTextRender; } |