1
1
Fork 0
mirror of https://github.com/QB64-Phoenix-Edition/QB64pe.git synced 2024-07-06 00:00:22 +00:00

Fix GetStringPixelWidth()

This commit is contained in:
Samuel Gomes 2023-04-26 21:37:36 +05:30
parent c033c624ac
commit 2d650cf1fe
2 changed files with 58 additions and 63 deletions

View file

@ -551,6 +551,17 @@ struct FontManager {
}
}
// Adjust for the last glyph
if (glyph) {
auto adjust = glyph->advanceWidth;
if (adjust < glyph->size.x)
adjust = glyph->size.x;
if (glyph->bearing.x > 0 && (glyph->size.x + glyph->bearing.x) > adjust)
adjust = glyph->size.x + glyph->bearing.x;
width = (width - glyph->advanceWidth) + adjust;
}
return width;
}
};
@ -899,6 +910,41 @@ int32_t FontWidth(int32_t fh) {
return 0;
}
/// @brief Returns the length of an UTF32 codepoint string in pixels
/// @param fh A valid font
/// @param codepoint The UTF32 codepoint array
/// @param codepoints The number of codepoints
/// @return Length in pixels
int32_t FontPrintWidthUTF32(int32_t fh, const uint32_t *codepoint, int32_t codepoints) {
if (codepoints > 0) {
FONT_DEBUG_CHECK(IS_FONT_HANDLE_VALID(fh));
// Get the actual width in pixels
return fontManager.fonts[fh]->GetStringPixelWidth((FT_ULong *)codepoint, codepoints);
}
return 0;
}
/// @brief Returns the length of an ASCII codepoint string in pixels
/// @param fh A valid font
/// @param codepoint The ASCII codepoint array
/// @param codepoints The number of codepoints
/// @return Length in pixels
int32_t FontPrintWidthASCII(int32_t fh, const uint8_t *codepoint, int32_t codepoints) {
if (codepoints > 0) {
FONT_DEBUG_CHECK(IS_FONT_HANDLE_VALID(fh));
// Atempt to convert the string to UTF32
if (utf32.ConvertASCII(codepoint, codepoints)) {
// Get the actual width in pixels
return FontPrintWidthUTF32(fh, (uint32_t *)utf32.codepoint, utf32.codepoints);
}
}
return 0;
}
/// @brief Master rendering routine (to be called by all other functions). None of the pointer args can be NULL
/// @param fh A valid font handle
/// @param codepoint A pointer to an array of UTF-32 codepoints that needs to be rendered
@ -922,7 +968,7 @@ bool FontRenderTextUTF32(int32_t fh, const uint32_t *codepoint, int32_t codepoin
return codepoints == 0; // true if zero, false if -ve
auto isMonochrome = options & FONT_RENDER_MONOCHROME; // do we need to do monochrome rendering?
auto outBufW = fnt->GetStringPixelWidth((FT_ULong *)codepoint, (FT_ULong)codepoints); // get the total buffer width
auto outBufW = fnt->GetStringPixelWidth((FT_ULong *)codepoint, codepoints); // get the total buffer width
auto outBufH = fnt->defaultHeight; // height is always set by the QB64
auto outBuf = (uint8_t *)calloc(outBufW, outBufH);
if (!outBuf)
@ -1002,57 +1048,6 @@ bool FontRenderTextASCII(int32_t fh, const uint8_t *codepoint, int32_t codepoint
return false;
}
/// @brief Returns the length of an UTF32 codepoint string in pixels
/// @param fh A valid font
/// @param codepoint The UTF32 codepoint array
/// @param codepoints The number of codepoints
/// @return Length in pixels
int32_t FontPrintWidthUTF32(int32_t fh, const uint32_t *codepoint, int32_t codepoints) {
// If we are just asking for the width of one codepoint then return the true width
// This can helps stuff like PRINT that prints one char at a time to avoid text to overlap and clip
if (codepoints == 1) {
FONT_DEBUG_CHECK(IS_FONT_HANDLE_VALID(fh));
auto fnt = fontManager.fonts[fh];
if (fnt->monospaceWidth)
return fnt->monospaceWidth; // we can avoid the multiplication
auto cp = codepoint[0];
if (fnt->CacheGlyph(cp)) {
auto glyph = fnt->glyphs[cp];
return std::max((glyph->size.x + glyph->bearing.x), std::max(glyph->advanceWidth, glyph->size.x));
}
} else if (codepoints > 1) {
FONT_DEBUG_CHECK(IS_FONT_HANDLE_VALID(fh));
// Get the actual width in pixels
return fontManager.fonts[fh]->GetStringPixelWidth((FT_ULong *)codepoint, codepoints);
}
return 0;
}
/// @brief Returns the length of an ASCII codepoint string in pixels
/// @param fh A valid font
/// @param codepoint The ASCII codepoint array
/// @param codepoints The number of codepoints
/// @return Length in pixels
int32_t FontPrintWidthASCII(int32_t fh, const uint8_t *codepoint, int32_t codepoints) {
if (codepoints > 0) {
FONT_DEBUG_CHECK(IS_FONT_HANDLE_VALID(fh));
// Atempt to convert the string to UTF32
if (utf32.ConvertASCII(codepoint, codepoints)) {
// Get the actual width in pixels
return FontPrintWidthUTF32(fh, (uint32_t *)utf32.codepoint, utf32.codepoints);
}
}
return 0;
}
/// @brief Return the true font height in pixel
/// @param qb64_fh A QB64 font handle (this can be a builtin font as well)
/// @param passed Optional arguments flag
@ -1094,7 +1089,7 @@ int32_t func__UPrintHeight(int32_t qb64_fh, int32_t passed) {
auto fnt = fontManager.fonts[font[qb64_fh]];
auto face = fnt->face;
return (float)(face->ascender - face->descender) / (float)face->units_per_EM * (float)fnt->defaultHeight;
return lroundf((float)(face->ascender - face->descender) / (float)face->units_per_EM * (float)fnt->defaultHeight);
}
/// @brief Returns the text widht in pixels
@ -1190,7 +1185,7 @@ int32_t func__UPrintLineSpacing(int32_t qb64_fh, int32_t passed) {
auto fnt = fontManager.fonts[font[qb64_fh]];
auto face = fnt->face;
return ((float)(face->height) / (float)face->units_per_EM * (float)fnt->defaultHeight) + 2;
return lroundf(((float)(face->height) / (float)face->units_per_EM * (float)fnt->defaultHeight) + 2.0f);
}
/// @brief This renders text on an active destination (graphics mode only) using the currently selected color
@ -1216,7 +1211,7 @@ void sub__UPrint(int32_t start_x, int32_t start_y, const qbs *text, int32_t max_
if (max_width < 1)
return;
} else {
max_width = INT32_MAX;
max_width = 0;
}
// Check UTF argument
@ -1283,7 +1278,7 @@ void sub__UPrint(int32_t start_x, int32_t start_y, const qbs *text, int32_t max_
if (cp > 255)
cp = 32; // our built-in fonts only has ASCII glyphs
if (pen.x + 8 > start_x + max_width)
if (max_width && pen.x + 8 > start_x + max_width)
break;
switch (qb64_fh) {
@ -1318,7 +1313,7 @@ void sub__UPrint(int32_t start_x, int32_t start_y, const qbs *text, int32_t max_
auto fnt = fontManager.fonts[font[qb64_fh]];
auto isMonochrome = write_page->compatible_mode != 32 || write_page->alpha_disabled; // do we need to do monochrome rendering?
pen.y += (float)fnt->face->ascender / (float)fnt->face->units_per_EM * (float)fnt->defaultHeight;
pen.y += lroundf((float)fnt->face->ascender / (float)fnt->face->units_per_EM * (float)fnt->defaultHeight);
if (fnt->monospaceWidth) {
for (auto i = 0; i < codepoints; i++) {
@ -1327,7 +1322,7 @@ void sub__UPrint(int32_t start_x, int32_t start_y, const qbs *text, int32_t max_
if (fnt->CacheGlyph(cp)) {
auto glyph = fnt->glyphs[cp];
if (pen.x + fnt->monospaceWidth > start_x + max_width)
if (max_width && pen.x + fnt->monospaceWidth > start_x + max_width)
break;
if (isMonochrome) {
@ -1354,14 +1349,14 @@ void sub__UPrint(int32_t start_x, int32_t start_y, const qbs *text, int32_t max_
if (fnt->CacheGlyph(cp)) {
glyph = fnt->glyphs[cp];
if (pen.x + glyph->size.x > start_x + max_width)
if (max_width && pen.x + glyph->size.x > start_x + max_width)
break;
// Add kerning advance width if kerning table is available
if (hasKerning && previousGlyph && glyph) {
FT_Vector delta;
FT_Get_Kerning(fnt->face, previousGlyph->index, glyph->index, FT_KERNING_DEFAULT, &delta);
pen.x += (float)delta.x / (float)fnt->face->units_per_EM * (float)fnt->defaultHeight;
pen.x += delta.x / 64;
}
if (isMonochrome) {

View file

@ -1437,7 +1437,7 @@ id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
id.ret = LONGTYPE - ISPOINTER
id.hr_syntax = "_UPRINTHEIGHT[(fontHandle&)]"
id.hr_syntax = "_UPRINTHEIGHT&[(fontHandle&)]"
regid
clearid
@ -1449,7 +1449,7 @@ id.args = 3
id.arg = MKL$(STRINGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?[,[?][,[?]]]"
id.ret = LONGTYPE - ISPOINTER
id.hr_syntax = "_UPRINTWIDTH(text$[, utfEncoding&][, fontHandle&])"
id.hr_syntax = "_UPRINTWIDTH&(text$[, utfEncoding&][, fontHandle&])"
regid
clearid
@ -1461,7 +1461,7 @@ id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
id.ret = LONGTYPE - ISPOINTER
id.hr_syntax = "_UPRINTLINESPACING[(fontHandle&)]"
id.hr_syntax = "_UPRINTLINESPACING&[(fontHandle&)]"
regid
regid