aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/Common/UI/UIBitmapFont.cpp
diff options
context:
space:
mode:
authordaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
committerdaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
commitb691c43c44ff180d10e7d4a9afc83b98551ff586 (patch)
tree3e9849222cbc6ba49f2f1fc6e5fe7179632c7390 /Minecraft.Client/Common/UI/UIBitmapFont.cpp
parentdef8cb415354ac390b7e89052a50605285f1aca9 (diff)
Initial commit
Diffstat (limited to 'Minecraft.Client/Common/UI/UIBitmapFont.cpp')
-rw-r--r--Minecraft.Client/Common/UI/UIBitmapFont.cpp364
1 files changed, 364 insertions, 0 deletions
diff --git a/Minecraft.Client/Common/UI/UIBitmapFont.cpp b/Minecraft.Client/Common/UI/UIBitmapFont.cpp
new file mode 100644
index 00000000..ec49eea3
--- /dev/null
+++ b/Minecraft.Client/Common/UI/UIBitmapFont.cpp
@@ -0,0 +1,364 @@
+#include "stdafx.h"
+
+#include "BufferedImage.h"
+#include "UIFontData.h"
+
+#include <unordered_set>
+
+#include "UIBitmapFont.h"
+
+
+/////////////////////////////
+// UI Abstract Bitmap Font //
+/////////////////////////////
+
+UIAbstractBitmapFont::~UIAbstractBitmapFont()
+{
+ if (m_registered) IggyFontRemoveUTF8( m_fontname.c_str(),-1,IGGY_FONTFLAG_none );
+ delete m_bitmapFontProvider;
+}
+
+
+UIAbstractBitmapFont::UIAbstractBitmapFont(const string &fontname)
+{
+ m_fontname = fontname;
+
+ m_registered = false;
+
+ m_bitmapFontProvider = new IggyBitmapFontProvider();
+ m_bitmapFontProvider->get_font_metrics = &UIAbstractBitmapFont::GetFontMetrics_Callback;
+ m_bitmapFontProvider->get_glyph_for_codepoint = &UIAbstractBitmapFont::GetCodepointGlyph_Callback;
+ m_bitmapFontProvider->get_glyph_metrics = &UIAbstractBitmapFont::GetGlyphMetrics_Callback;
+ m_bitmapFontProvider->is_empty = &UIAbstractBitmapFont::IsGlyphEmpty_Callback;
+ m_bitmapFontProvider->get_kerning = &UIAbstractBitmapFont::GetKerningForGlyphPair_Callback;
+ m_bitmapFontProvider->can_bitmap = &UIAbstractBitmapFont::CanProvideBitmap_Callback;
+ m_bitmapFontProvider->get_bitmap = &UIAbstractBitmapFont::GetGlyphBitmap_Callback;
+ m_bitmapFontProvider->free_bitmap = &UIAbstractBitmapFont::FreeGlyphBitmap_Callback;
+ m_bitmapFontProvider->userdata = this;
+}
+
+void UIAbstractBitmapFont::registerFont()
+{
+ if(m_registered)
+ {
+ return;
+ }
+
+ m_bitmapFontProvider->num_glyphs = m_numGlyphs;
+
+ IggyFontInstallBitmapUTF8( m_bitmapFontProvider,m_fontname.c_str(),-1,IGGY_FONTFLAG_none );
+ IggyFontSetIndirectUTF8( m_fontname.c_str(),-1 ,IGGY_FONTFLAG_all ,m_fontname.c_str() ,-1 ,IGGY_FONTFLAG_none );
+ m_registered = true;
+}
+
+IggyFontMetrics * RADLINK UIAbstractBitmapFont::GetFontMetrics_Callback(void *user_context,IggyFontMetrics *metrics)
+{
+ return ((UIAbstractBitmapFont *) user_context)->GetFontMetrics(metrics);
+}
+
+S32 RADLINK UIAbstractBitmapFont::GetCodepointGlyph_Callback(void *user_context,U32 codepoint)
+{
+ return ((UIAbstractBitmapFont *) user_context)->GetCodepointGlyph(codepoint);
+}
+
+IggyGlyphMetrics * RADLINK UIAbstractBitmapFont::GetGlyphMetrics_Callback(void *user_context,S32 glyph,IggyGlyphMetrics *metrics)
+{
+ return ((UIAbstractBitmapFont *) user_context)->GetGlyphMetrics(glyph,metrics);
+}
+
+rrbool RADLINK UIAbstractBitmapFont::IsGlyphEmpty_Callback(void *user_context,S32 glyph)
+{
+ return ((UIAbstractBitmapFont *) user_context)->IsGlyphEmpty(glyph);
+}
+
+F32 RADLINK UIAbstractBitmapFont::GetKerningForGlyphPair_Callback(void *user_context,S32 first_glyph,S32 second_glyph)
+{
+ return ((UIAbstractBitmapFont *) user_context)->GetKerningForGlyphPair(first_glyph,second_glyph);
+}
+
+rrbool RADLINK UIAbstractBitmapFont::CanProvideBitmap_Callback(void *user_context,S32 glyph,F32 pixel_scale)
+{
+ return ((UIAbstractBitmapFont *) user_context)->CanProvideBitmap(glyph,pixel_scale);
+}
+
+rrbool RADLINK UIAbstractBitmapFont::GetGlyphBitmap_Callback(void *user_context,S32 glyph,F32 pixel_scale,IggyBitmapCharacter *bitmap)
+{
+ return ((UIAbstractBitmapFont *) user_context)->GetGlyphBitmap(glyph,pixel_scale,bitmap);
+}
+
+void RADLINK UIAbstractBitmapFont::FreeGlyphBitmap_Callback(void *user_context,S32 glyph,F32 pixel_scale,IggyBitmapCharacter *bitmap)
+{
+ return ((UIAbstractBitmapFont *) user_context)->FreeGlyphBitmap(glyph,pixel_scale,bitmap);
+}
+
+UIBitmapFont::UIBitmapFont( SFontData &sfontdata )
+ : UIAbstractBitmapFont( sfontdata.m_strFontName )
+{
+ m_numGlyphs = sfontdata.m_uiGlyphCount;
+
+ BufferedImage bimg(sfontdata.m_wstrFilename);
+ int *bimgData = bimg.getData();
+
+ m_cFontData = new CFontData(sfontdata, bimgData);
+
+ //delete [] bimgData;
+}
+
+UIBitmapFont::~UIBitmapFont()
+{
+ m_cFontData->release();
+}
+
+//Callback function type for returning vertical font metrics
+IggyFontMetrics *UIBitmapFont::GetFontMetrics(IggyFontMetrics *metrics)
+{
+ //Description
+ // Vertical metrics for a font
+ //Members
+ // ascent - extent of characters above baseline (positive)
+ // descent - extent of characters below baseline (positive)
+ // line_gap - spacing between one row's descent and the next line's ascent
+ // average_glyph_width_for_tab_stops - spacing of "average" character for computing default tab stops
+ // largest_glyph_bbox_y1 - lowest point below baseline of any character in the font
+
+ metrics->ascent = m_cFontData->getFontData()->m_fAscent;
+ metrics->descent = m_cFontData->getFontData()->m_fDescent;
+
+ metrics->average_glyph_width_for_tab_stops = 8.0f;
+
+ // This is my best guess, there's no reference to a specific glyph here
+ // so aren't these just exactly the same.
+ metrics->largest_glyph_bbox_y1 = metrics->descent;
+
+ // metrics->line_gap; // 4J-JEV: Sean said this does nothing.
+
+ return metrics;
+}
+
+//Callback function type for mapping 32-bit unicode code point to internal font glyph number; use IGGY_GLYPH_INVALID to mean "invalid character"
+S32 UIBitmapFont::GetCodepointGlyph(U32 codepoint)
+{
+ // 4J-JEV: Change "right single quotation marks" to apostrophies.
+ if (codepoint == 0x2019) codepoint = 0x27;
+
+ return m_cFontData->getGlyphId(codepoint);
+}
+
+//Callback function type for returning horizontal metrics for each glyph
+IggyGlyphMetrics * UIBitmapFont::GetGlyphMetrics(S32 glyph,IggyGlyphMetrics *metrics)
+{
+ // 4J-JEV: Information about 'Glyph Metrics'.
+ // http://freetype.sourceforge.net/freetype2/docs/glyphs/glyphs-3.html - Overview.
+ // http://en.wikipedia.org/wiki/Kerning#Kerning_values - 'Font Units'
+
+ //Description
+ // Horizontal metrics for a glyph
+ //Members
+ // x0 y0 x1 y1 - bounding box
+ // advance - horizontal distance to move character origin after drawing this glyph
+
+
+ /* 4J-JEV: *IMPORTANT*
+ *
+ * I believe these are measured wrt the scale mentioned in GetGlyphBitmap
+ * i.e. 1.0f == pixel_scale,
+ *
+ * However we do not have that information here, then all these values need to be
+ * the same for every scale in this font.
+ *
+ * We have 2 scales of bitmap glyph, and we can only scale these up by powers of 2
+ * otherwise the fonts will become blurry. The appropriate glyph is chosen in
+ * 'GetGlyphBitmap' however we need to set the horizontal sizes here.
+ */
+
+ float glyphAdvance = m_cFontData->getAdvance(glyph);
+
+ // 4J-JEV: Anything outside this measurement will be
+ // cut off if it's at the start or end of the row.
+ metrics->x0 = 0.0f;
+
+ if ( m_cFontData->glyphIsWhitespace(glyph) )
+ metrics->x1 = 0.0f;
+ else
+ metrics->x1 = glyphAdvance;
+
+ // The next Glyph just starts right after this one.
+ metrics->advance = glyphAdvance;
+
+ //app.DebugPrintf("[UIBitmapFont] GetGlyphMetrics:\n\tmetrics->advance == %f,\n", metrics->advance);
+
+ // These don't do anything either.
+ metrics->y0 = 0.0f; metrics->y1 = 1.0f;
+
+ return metrics;
+}
+
+//Callback function type that should return true iff the glyph has no visible elements
+rrbool UIBitmapFont::IsGlyphEmpty (S32 glyph)
+{
+ if (m_cFontData->glyphIsWhitespace(glyph)) return true;
+ return false;//app.DebugPrintf("Is glyph %d empty? %s\n",glyph,isEmpty?"TRUE":"FALSE");
+}
+
+//Callback function type for returning the kerning amount for a given pair of glyphs
+F32 UIBitmapFont::GetKerningForGlyphPair(S32 first_glyph,S32 second_glyph)
+{
+ //UIBitmapFont *uiFont = (UIBitmapFont *) user_context;
+ //app.DebugPrintf("Get kerning for glyph pair %d,%d\n",first_glyph,second_glyph);
+
+ // 4J-JEV: Yet another field that doesn't do anything.
+ // Only set out of paranoia.
+ return 0.0f;
+}
+
+//Callback function type used for reporting whether a bitmap supports a given glyph at the given scale
+rrbool UIBitmapFont::CanProvideBitmap(S32 glyph,F32 pixel_scale)
+{
+ //app.DebugPrintf("Can provide bitmap for glyph %d at scale %f? %s\n",glyph,pixel_scale,canProvideBitmap?"TRUE":"FALSE");
+ return true;
+}
+
+// Description
+// Callback function type used for getting the bitmap for a given glyph
+// Parameters
+// glyph The glyph to compute/get the bitmap for
+// pixel_scale The scale factor (pseudo point size) requested by the textfield,adjusted for display resolution
+// bitmap The structure to store the bitmap into
+rrbool UIBitmapFont::GetGlyphBitmap(S32 glyph,F32 pixel_scale,IggyBitmapCharacter *bitmap)
+{
+ //Description
+ // Data structure used to return to Iggy the bitmap to use for a glyph
+ //Members
+ // pixels_one_per_byte - pixels startin with the top-left-most; 0 is transparent and 255 is opaque
+ // width_in_pixels - this is the width of the bitmap data
+ // height_in_pixels - this is the height of the bitmap data
+ // stride_in_bytes - the distance from one row to the next
+ // oversample - this is the amount of oversampling (0 or 1 = not oversample,2 = 2x oversampled,4 = 4x oversampled)
+ // point_sample - if true,the bitmap will be drawn with point sampling; if false,it will be drawn with bilinear
+ // top_left_x - the offset of the top left corner from the character origin
+ // top_left_y - the offset of the top left corner from the character origin
+ // pixel_scale_correct - the pixel_scale at which this character should be displayed at displayed_width_in_pixels
+ // pixel_scale_min - the smallest pixel_scale to allow using this character (scaled down)
+ // pixel_scale_max - the largest pixels cale to allow using this character (scaled up)
+ // user_context_for_free - you can use this to store data to access on the corresponding free call
+
+ int row = 0,col = 0;
+ m_cFontData->getPos(glyph,row,col);
+
+ // Skip to glyph start.
+ bitmap->pixels_one_per_byte = m_cFontData->topLeftPixel(row,col);
+
+ // Choose a reasonable glyph scale.
+ float glyphScale = 1.0f, truePixelScale = 1.0f / m_cFontData->getFontData()->m_fAdvPerPixel;
+ F32 targetPixelScale = pixel_scale;
+ //if(!RenderManager.IsWidescreen())
+ //{
+ // // Fix for different scales in 480
+ // targetPixelScale = pixel_scale*2/3;
+ //}
+ while ( (0.5f + glyphScale) * truePixelScale < targetPixelScale)
+ glyphScale++;
+
+ // 4J-JEV: Debug code to check which font sizes are being used.
+#if (!defined _CONTENT_PACKAGE) && (VERBOSE_FONT_OUTPUT > 0)
+
+ struct DebugData
+ {
+ string name;
+ long scale;
+ long mul;
+
+ bool operator==(const DebugData& dd) const
+ {
+ if ( name.compare(dd.name) != 0 ) return false;
+ else if (scale != dd.scale) return false;
+ else if (mul != dd.mul) return false;
+ else return true;
+ }
+ };
+
+ static long long lastPrint = System::currentTimeMillis();
+ static unordered_set<DebugData> debug_fontSizesRequested;
+
+ {
+ DebugData dData = { m_cFontData->getFontName(), (long) pixel_scale, (long) glyphScale };
+ debug_fontSizesRequested.insert(dData);
+
+ if ( (lastPrint - System::currentTimeMillis()) > VERBOSE_FONT_OUTPUT )
+ {
+ app.DebugPrintf("<UIBitmapFont> Requested font/sizes:\n");
+
+ unordered_set<DebugData>::iterator itr;
+ for ( itr = debug_fontSizesRequested.begin();
+ itr != debug_fontSizesRequested.end();
+ itr++
+ )
+ {
+ app.DebugPrintf("<UIBitmapFont>\t- %s:%i\t(x%i)\n", itr->name.c_str(), itr->scale, itr->mul);
+ }
+
+ lastPrint = System::currentTimeMillis();
+ debug_fontSizesRequested.clear();
+ }
+ }
+#endif
+
+ //app.DebugPrintf("Request glyph_%d (U+%.4X) at %f, converted to %f (%f)\n",
+ // glyph, GetUnicode(glyph), pixel_scale, targetPixelScale, glyphScale);
+
+ // It is not necessary to shrink the glyph width here
+ // as its already been done in 'GetGlyphMetrics' by:
+ // > metrics->x1 = m_kerningTable[glyph] * ratio;
+ bitmap->width_in_pixels = m_cFontData->getFontData()->m_uiGlyphWidth;
+ bitmap->height_in_pixels = m_cFontData->getFontData()->m_uiGlyphHeight;
+
+ /* 4J-JEV: This is to do with glyph placement,
+ * and not the position in the archive.
+ * I don't know why the 0.65 is needed, or what it represents,
+ * although it doesn't look like its the baseline.
+ */
+ bitmap->top_left_x = 0;
+
+ // 4J-PB - this was chopping off the top of the characters, so accented ones were losing a couple of pixels at the top
+ // DaveK has reduced the height of the accented capitalised characters, and we've dropped this from 0.65 to 0.64
+ bitmap->top_left_y = -((S32) m_cFontData->getFontData()->m_uiGlyphHeight) * m_cFontData->getFontData()->m_fAscent;
+
+ bitmap->oversample = 0;
+ bitmap->point_sample = true;
+
+ // 4J-JEV:
+ // pixel_scale == font size chosen in flash.
+ // bitmap->pixel_scale_correct = (float) m_glyphHeight; // Scales the glyph to desired size.
+ // bitmap->pixel_scale_correct = pixel_scale; // Always the same size (not desired size).
+ // bitmap->pixel_scale_correct = pixel_scale * 0.5; // Doubles original size.
+ // bitmap->pixel_scale_correct = pixel_scale * 2; // Halves original size.
+
+ // Actual scale, and possible range of scales.
+ bitmap->pixel_scale_correct = pixel_scale / glyphScale;
+ bitmap->pixel_scale_max = 99.0f;
+ bitmap->pixel_scale_min = 0.0f;
+
+ /* 4J-JEV: Some of Sean's code.
+ int glyphScaleMin = 1;
+ int glyphScaleMax = 3;
+ float actualScale = pixel_scale / glyphScale;
+ bitmap->pixel_scale_correct = actualScale;
+ bitmap->pixel_scale_min = actualScale * glyphScaleMin * 0.999f;
+ bitmap->pixel_scale_max = actualScale * glyphScaleMax * 1.001f; */
+
+ // 4J-JEV: Nothing to do with glyph placement,
+ // entirely to do with cropping your glyph out of an archive.
+ bitmap->stride_in_bytes = m_cFontData->getFontData()->m_uiGlyphMapX;
+
+ // 4J-JEV: Additional information needed to release memory afterwards.
+ bitmap->user_context_for_free = NULL;
+
+ return true;
+}
+
+//Callback function type for freeing a bitmap shape returned by GetGlyphBitmap
+void RADLINK UIBitmapFont::FreeGlyphBitmap(S32 glyph,F32 pixel_scale,IggyBitmapCharacter *bitmap)
+{
+ // We don't need to free anything,it just comes from the archive.
+ //app.DebugPrintf("Free bitmap for glyph %d at scale %f\n",glyph,pixel_scale);
+}