diff options
Diffstat (limited to 'src/emu/rendfont.cpp')
-rw-r--r-- | src/emu/rendfont.cpp | 377 |
1 files changed, 164 insertions, 213 deletions
diff --git a/src/emu/rendfont.cpp b/src/emu/rendfont.cpp index c5debb5f055..259d7731fe5 100644 --- a/src/emu/rendfont.cpp +++ b/src/emu/rendfont.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb /*************************************************************************** - rendfont.c + rendfont.cpp Rendering system font management. @@ -10,11 +10,18 @@ #include "emu.h" #include "rendfont.h" + #include "emuopts.h" -#include "coreutil.h" +#include "fileio.h" +#include "render.h" + +#include "corestr.h" +#include "multibyte.h" +#include "path.h" #include "osdepend.h" #include "uismall.fh" +#include "unicode.h" #include "ui/uicmd14.fh" #include "ui/cmddata.h" @@ -119,13 +126,14 @@ public: static constexpr unsigned MAJVERSION = 1; static constexpr unsigned MINVERSION = 0; - bool read(emu_file &f) + bool read(util::read_stream &f) { - return f.read(m_data, sizeof(m_data)) == sizeof(m_data); + auto const [err, actual] = util::read(f, m_data, sizeof(m_data)); + return !err && (actual == sizeof(m_data)); } - bool write(emu_file &f) + bool write(util::write_stream &f) { - return f.write(m_data, sizeof(m_data)) == sizeof(m_data); + return !util::write(f, m_data, sizeof(m_data)).first; } bool check_magic() const @@ -142,51 +150,27 @@ public: } u64 get_original_length() const { - return - (u64(m_data[OFFS_ORIGLENGTH + 0]) << (7 * 8)) | - (u64(m_data[OFFS_ORIGLENGTH + 1]) << (6 * 8)) | - (u64(m_data[OFFS_ORIGLENGTH + 2]) << (5 * 8)) | - (u64(m_data[OFFS_ORIGLENGTH + 3]) << (4 * 8)) | - (u64(m_data[OFFS_ORIGLENGTH + 4]) << (3 * 8)) | - (u64(m_data[OFFS_ORIGLENGTH + 5]) << (2 * 8)) | - (u64(m_data[OFFS_ORIGLENGTH + 6]) << (1 * 8)) | - (u64(m_data[OFFS_ORIGLENGTH + 7]) << (0 * 8)); + return get_u64be(m_data + OFFS_ORIGLENGTH); } u32 get_original_hash() const { - return - (u32(m_data[OFFS_ORIGHASH + 0]) << (3 * 8)) | - (u32(m_data[OFFS_ORIGHASH + 1]) << (2 * 8)) | - (u32(m_data[OFFS_ORIGHASH + 2]) << (1 * 8)) | - (u32(m_data[OFFS_ORIGHASH + 3]) << (0 * 8)); + return get_u32be(m_data + OFFS_ORIGHASH); } u32 get_glyph_count() const { - return - (u32(m_data[OFFS_GLYPHCOUNT + 0]) << (3 * 8)) | - (u32(m_data[OFFS_GLYPHCOUNT + 1]) << (2 * 8)) | - (u32(m_data[OFFS_GLYPHCOUNT + 2]) << (1 * 8)) | - (u32(m_data[OFFS_GLYPHCOUNT + 3]) << (0 * 8)); + return get_u32be(m_data + OFFS_GLYPHCOUNT); } u16 get_height() const { - return - (u16(m_data[OFFS_HEIGHT + 0]) << (1 * 8)) | - (u16(m_data[OFFS_HEIGHT + 1]) << (0 * 8)); + return get_u16be(m_data + OFFS_HEIGHT); } s16 get_y_offset() const { - return - (u16(m_data[OFFS_YOFFSET + 0]) << (1 * 8)) | - (u16(m_data[OFFS_YOFFSET + 1]) << (0 * 8)); + return get_u16be(m_data + OFFS_YOFFSET); } s32 get_default_character() const { - return - (u32(m_data[OFFS_DEFCHAR + 0]) << (3 * 8)) | - (u32(m_data[OFFS_DEFCHAR + 1]) << (2 * 8)) | - (u32(m_data[OFFS_DEFCHAR + 2]) << (1 * 8)) | - (u32(m_data[OFFS_DEFCHAR + 3]) << (0 * 8)); + return get_u32be(m_data + OFFS_DEFCHAR); } void set_magic() @@ -200,45 +184,27 @@ public: } void set_original_length(u64 value) { - m_data[OFFS_ORIGLENGTH + 0] = u8((value >> (7 * 8)) & 0x00ff); - m_data[OFFS_ORIGLENGTH + 1] = u8((value >> (6 * 8)) & 0x00ff); - m_data[OFFS_ORIGLENGTH + 2] = u8((value >> (5 * 8)) & 0x00ff); - m_data[OFFS_ORIGLENGTH + 3] = u8((value >> (4 * 8)) & 0x00ff); - m_data[OFFS_ORIGLENGTH + 4] = u8((value >> (3 * 8)) & 0x00ff); - m_data[OFFS_ORIGLENGTH + 5] = u8((value >> (2 * 8)) & 0x00ff); - m_data[OFFS_ORIGLENGTH + 6] = u8((value >> (1 * 8)) & 0x00ff); - m_data[OFFS_ORIGLENGTH + 7] = u8((value >> (0 * 8)) & 0x00ff); + put_u64be(m_data + OFFS_ORIGLENGTH, value); } void set_original_hash(u32 value) { - m_data[OFFS_ORIGHASH + 0] = u8((value >> (3 * 8)) & 0x00ff); - m_data[OFFS_ORIGHASH + 1] = u8((value >> (2 * 8)) & 0x00ff); - m_data[OFFS_ORIGHASH + 2] = u8((value >> (1 * 8)) & 0x00ff); - m_data[OFFS_ORIGHASH + 3] = u8((value >> (0 * 8)) & 0x00ff); + put_u32be(m_data + OFFS_ORIGHASH, value); } void set_glyph_count(u32 value) { - m_data[OFFS_GLYPHCOUNT + 0] = u8((value >> (3 * 8)) & 0x00ff); - m_data[OFFS_GLYPHCOUNT + 1] = u8((value >> (2 * 8)) & 0x00ff); - m_data[OFFS_GLYPHCOUNT + 2] = u8((value >> (1 * 8)) & 0x00ff); - m_data[OFFS_GLYPHCOUNT + 3] = u8((value >> (0 * 8)) & 0x00ff); + put_u32be(m_data + OFFS_GLYPHCOUNT, value); } void set_height(u16 value) { - m_data[OFFS_HEIGHT + 0] = u8((value >> (1 * 8)) & 0x00ff); - m_data[OFFS_HEIGHT + 1] = u8((value >> (0 * 8)) & 0x00ff); + put_u16be(m_data + OFFS_HEIGHT, value); } void set_y_offset(s16 value) { - m_data[OFFS_YOFFSET + 0] = u8((value >> (1 * 8)) & 0x00ff); - m_data[OFFS_YOFFSET + 1] = u8((value >> (0 * 8)) & 0x00ff); + put_u16be(m_data + OFFS_YOFFSET, value); } void set_default_character(s32 value) { - m_data[OFFS_DEFCHAR + 0] = u8((value >> (3 * 8)) & 0x00ff); - m_data[OFFS_DEFCHAR + 1] = u8((value >> (2 * 8)) & 0x00ff); - m_data[OFFS_DEFCHAR + 2] = u8((value >> (1 * 8)) & 0x00ff); - m_data[OFFS_DEFCHAR + 3] = u8((value >> (0 * 8)) & 0x00ff); + put_u32be(m_data + OFFS_DEFCHAR, value); } private: @@ -278,74 +244,52 @@ public: u32 get_encoding() const { - return - (u32(m_ptr[OFFS_ENCODING + 0]) << (3 * 8)) | - (u32(m_ptr[OFFS_ENCODING + 1]) << (2 * 8)) | - (u32(m_ptr[OFFS_ENCODING + 2]) << (1 * 8)) | - (u32(m_ptr[OFFS_ENCODING + 3]) << (0 * 8)); + return get_u32be(m_ptr + OFFS_ENCODING); } u16 get_x_advance() const { - return - (u16(m_ptr[OFFS_XADVANCE + 0]) << (1 * 8)) | - (u16(m_ptr[OFFS_XADVANCE + 1]) << (0 * 8)); + return get_u16be(m_ptr + OFFS_XADVANCE); } s16 get_bb_x_offset() const { - return - (u16(m_ptr[OFFS_BBXOFFSET + 0]) << (1 * 8)) | - (u16(m_ptr[OFFS_BBXOFFSET + 1]) << (0 * 8)); + return get_u16be(m_ptr + OFFS_BBXOFFSET); } s16 get_bb_y_offset() const { - return - (u16(m_ptr[OFFS_BBYOFFSET + 0]) << (1 * 8)) | - (u16(m_ptr[OFFS_BBYOFFSET + 1]) << (0 * 8)); + return get_u16be(m_ptr + OFFS_BBYOFFSET); } u16 get_bb_width() const { - return - (u16(m_ptr[OFFS_BBWIDTH + 0]) << (1 * 8)) | - (u16(m_ptr[OFFS_BBWIDTH + 1]) << (0 * 8)); + return get_u16be(m_ptr + OFFS_BBWIDTH); } u16 get_bb_height() const { - return - (u16(m_ptr[OFFS_BBHEIGHT + 0]) << (1 * 8)) | - (u16(m_ptr[OFFS_BBHEIGHT + 1]) << (0 * 8)); + return get_u16be(m_ptr + OFFS_BBHEIGHT); } void set_encoding(u32 value) { - m_ptr[OFFS_ENCODING + 0] = u8((value >> (3 * 8)) & 0x00ff); - m_ptr[OFFS_ENCODING + 1] = u8((value >> (2 * 8)) & 0x00ff); - m_ptr[OFFS_ENCODING + 2] = u8((value >> (1 * 8)) & 0x00ff); - m_ptr[OFFS_ENCODING + 3] = u8((value >> (0 * 8)) & 0x00ff); + put_u32be(m_ptr + OFFS_ENCODING, value); } void set_x_advance(u16 value) { - m_ptr[OFFS_XADVANCE + 0] = u8((value >> (1 * 8)) & 0x00ff); - m_ptr[OFFS_XADVANCE + 1] = u8((value >> (0 * 8)) & 0x00ff); + put_u16be(m_ptr + OFFS_XADVANCE, value); } void set_bb_x_offset(s16 value) { - m_ptr[OFFS_BBXOFFSET + 0] = u8((value >> (1 * 8)) & 0x00ff); - m_ptr[OFFS_BBXOFFSET + 1] = u8((value >> (0 * 8)) & 0x00ff); + put_u16be(m_ptr + OFFS_BBXOFFSET, value); } void set_bb_y_offset(s16 value) { - m_ptr[OFFS_BBYOFFSET + 0] = u8((value >> (1 * 8)) & 0x00ff); - m_ptr[OFFS_BBYOFFSET + 1] = u8((value >> (0 * 8)) & 0x00ff); + put_u16be(m_ptr + OFFS_BBYOFFSET, value); } void set_bb_width(u16 value) { - m_ptr[OFFS_BBWIDTH + 0] = u8((value >> (1 * 8)) & 0x00ff); - m_ptr[OFFS_BBWIDTH + 1] = u8((value >> (0 * 8)) & 0x00ff); + put_u16be(m_ptr + OFFS_BBWIDTH, value); } void set_bb_height(u16 value) { - m_ptr[OFFS_BBHEIGHT + 0] = u8((value >> (1 * 8)) & 0x00ff); - m_ptr[OFFS_BBHEIGHT + 1] = u8((value >> (0 * 8)) & 0x00ff); + put_u16be(m_ptr + OFFS_BBHEIGHT, value); } bdc_table_entry &operator=(bdc_table_entry const &that) = default; @@ -372,35 +316,30 @@ private: } // anonymous namespace -void convert_command_glyph(std::string &str) +std::string convert_command_glyph(std::string_view str) { - (void)str.c_str(); // force NUL-termination - we depend on it later - std::size_t const len(str.length()); - std::vector<char> buf(2 * (len + 1)); + std::vector<char> buf(2 * (str.length() + 1)); std::size_t j(0); - for (std::size_t i = 0; len > i; ) + while (!str.empty()) { // decode UTF-8 char32_t uchar; - int const codelen(uchar_from_utf8(&uchar, &str[i], len - i)); + int const codelen(uchar_from_utf8(&uchar, str)); if (0 >= codelen) break; - i += codelen; + str.remove_prefix(codelen); // check for three metacharacters fix_command_t const *fixcmd(nullptr); switch (uchar) { case COMMAND_CONVERT_TEXT: - for (fix_strings_t *fixtext = convert_text; fixtext->glyph_code; ++fixtext) + for (fix_strings_t const *fixtext = convert_text; fixtext->glyph_code; ++fixtext) { - if (!fixtext->glyph_str_len) - fixtext->glyph_str_len = std::strlen(fixtext->glyph_str); - - if (!std::strncmp(fixtext->glyph_str, &str[i], fixtext->glyph_str_len)) + if (str.substr(0, fixtext->glyph_str.length()) == fixtext->glyph_str) { uchar = fixtext->glyph_code + COMMAND_UNICODE; - i += strlen(fixtext->glyph_str); + str.remove_prefix(fixtext->glyph_str.length()); break; } } @@ -416,20 +355,20 @@ void convert_command_glyph(std::string &str) } // this substitutes a single character - if (fixcmd) + if (fixcmd && !str.empty()) { - if (str[i] == uchar) + if (str[0] == uchar) { - ++i; + str.remove_prefix(1); } else { - while (fixcmd->glyph_code && (fixcmd->glyph_char != str[i])) + while (fixcmd->glyph_code && !str.empty() && fixcmd->glyph_char != str[0]) ++fixcmd; - if (fixcmd->glyph_code) + if (fixcmd->glyph_code && !str.empty()) { uchar = COMMAND_UNICODE + fixcmd->glyph_code; - ++i; + str.remove_prefix(1); } } } @@ -440,7 +379,7 @@ void convert_command_glyph(std::string &str) break; j += outlen; } - str.assign(&buf[0], j); + return std::string(&buf[0], j); } @@ -481,7 +420,7 @@ inline render_font::glyph &render_font::get_char(char32_t chnum) static glyph dummy_glyph; unsigned const page(chnum / 256); - if (page >= ARRAY_LENGTH(m_glyphs)) + if (page >= std::size(m_glyphs)) { if ((0 <= m_defchar) && (chnum != m_defchar)) return get_char(m_defchar); @@ -596,10 +535,9 @@ render_font::render_font(render_manager &manager, const char *filename) } // load the compiled in data instead - emu_file ramfile(OPEN_FLAG_READ); - osd_file::error const filerr(ramfile.open_ram(font_uismall, sizeof(font_uismall))); - if (osd_file::error::NONE == filerr) - load_cached(ramfile, 0, 0); + util::random_read::ptr ramfile = util::ram_read(font_uismall, sizeof(font_uismall)); + if (ramfile) + load_cached(*ramfile, 0, 0); render_font_command_glyph(); } @@ -664,14 +602,14 @@ void render_font::char_expand(char32_t chnum, glyph &gl) for (int y = 0; y < gl.bmheight; y++) { int desty = y + m_height_cmd + m_yoffs_cmd - gl.yoffs - gl.bmheight; - u32 *dest = (desty >= 0 && desty < m_height_cmd) ? &gl.bitmap.pix32(desty, 0) : nullptr; + u32 *dest = (desty >= 0 && desty < m_height_cmd) ? &gl.bitmap.pix(desty, 0) : nullptr; { for (int x = 0; x < gl.bmwidth; x++) { if (accumbit == 7) accum = *ptr++; if (dest != nullptr) - *dest++ = (accum & (1 << accumbit)) ? fgcol : bgcol; + *dest++ = BIT(accum, accumbit) ? fgcol : bgcol; accumbit = (accumbit - 1) & 7; } } @@ -723,7 +661,7 @@ void render_font::char_expand(char32_t chnum, glyph &gl) for (int y = 0; y < gl.bmheight; ++y) { int const desty(y + m_height + m_yoffs - gl.yoffs - gl.bmheight); - u32 *dest(((0 <= desty) && (m_height > desty)) ? &gl.bitmap.pix32(desty) : nullptr); + u32 *dest(((0 <= desty) && (m_height > desty)) ? &gl.bitmap.pix(desty) : nullptr); if (m_format == format::TEXT) { @@ -767,7 +705,7 @@ void render_font::char_expand(char32_t chnum, glyph &gl) if (accumbit == 7) accum = *ptr++; if (dest != nullptr) - *dest++ = (accum & (1 << accumbit)) ? fgcol : bgcol; + *dest++ = BIT(accum, accumbit) ? fgcol : bgcol; accumbit = (accumbit - 1) & 7; } } @@ -820,7 +758,8 @@ void render_font::get_scaled_bitmap_and_bounds(bitmap_argb32 &dest, float height bounds.min_y = 0; // compute x1,y1 from there based on the bitmap size - bounds.set_width(float(gl.bmwidth) * scale * aspect); + float width = float(gl.bmwidth) * scale * aspect; + bounds.set_width(width < 0.5f ? 0 : std::max(int(width), 1)); bounds.set_height(float(m_height) * scale); // if the bitmap isn't big enough, bail @@ -856,24 +795,23 @@ float render_font::char_width(float height, float aspect, char32_t ch) // at the given height //------------------------------------------------- -float render_font::string_width(float height, float aspect, const char *string) +float render_font::string_width(float height, float aspect, std::string_view string) { // loop over the string and accumulate widths int totwidth = 0; - const char *ends = string + strlen(string); - const char *s = string; char32_t schar; // loop over characters - while (*s != 0) + int scharcount; + while ((scharcount = uchar_from_utf8(&schar, string)) != 0) { - int scharcount = uchar_from_utf8(&schar, s, ends - s); + if (0 > scharcount) + schar = 0xfffd; + string.remove_prefix((0 > scharcount) ? 1 : scharcount); totwidth += get_char(schar).width; - s += scharcount; } - // scale the final result based on height return float(totwidth) * m_scale * height * aspect; } @@ -884,21 +822,19 @@ float render_font::string_width(float height, float aspect, const char *string) // UTF8-encoded string at the given height //------------------------------------------------- -float render_font::utf8string_width(float height, float aspect, const char *utf8string) +float render_font::utf8string_width(float height, float aspect, std::string_view utf8string) { - std::size_t const length = std::strlen(utf8string); - // loop over the string and accumulate widths - int count; s32 totwidth = 0; - for (std::size_t offset = 0U; offset < length; offset += unsigned(count)) + while (!utf8string.empty()) { char32_t uchar; - count = uchar_from_utf8(&uchar, utf8string + offset, length - offset); + int count = uchar_from_utf8(&uchar, utf8string); if (count < 0) break; totwidth += get_char(uchar).width; + utf8string.remove_prefix(count); } // scale the final result based on height @@ -913,16 +849,16 @@ float render_font::utf8string_width(float height, float aspect, const char *utf8 // and create a new cached version //------------------------------------------------- -bool render_font::load_cached_bdf(const char *filename) +bool render_font::load_cached_bdf(std::string_view filename) { - osd_file::error filerr; + std::error_condition filerr; u32 chunk; - u64 bytes; + std::size_t bytes; // first try to open the BDF itself emu_file file(m_manager.machine().options().font_path(), OPEN_FLAG_READ); filerr = file.open(filename); - if (filerr != osd_file::error::NONE) + if (filerr) return false; // determine the file size and allocate memory @@ -947,19 +883,17 @@ bool render_font::load_cached_bdf(const char *filename) m_rawdata.clear(); return false; } - u32 const hash(core_crc32(0, reinterpret_cast<u8 const *>(&m_rawdata[0]), bytes)); + u32 const hash(util::crc32_creator::simple(&m_rawdata[0], bytes)); // create the cached filename, changing the 'F' to a 'C' on the extension - std::string cachedname(filename); - if ((4U < cachedname.length()) && !core_stricmp(&cachedname[cachedname.length() - 4], ".bdf")) - cachedname.erase(cachedname.length() - 4); + std::string cachedname(filename, 0, filename.length() - ((4U < filename.length()) && core_filename_ends_with(filename, ".bdf") ? 4 : 0)); cachedname.append(".bdc"); // attempt to open the cached version of the font { emu_file cachefile(m_manager.machine().options().font_path(), OPEN_FLAG_READ); - filerr = cachefile.open(cachedname.c_str()); - if (filerr == osd_file::error::NONE) + filerr = cachefile.open(cachedname); + if (!filerr) { // if we have a cached version, load it bool const result = load_cached(cachefile, m_rawsize, hash); @@ -985,11 +919,25 @@ bool render_font::load_cached_bdf(const char *filename) m_rawdata[m_rawsize] = '\0'; // load the BDF - bool const result = load_bdf(); + bool result = load_bdf(); // if we loaded okay, create a cached one if (result) - save_cached(cachedname.c_str(), m_rawsize, hash); + { + osd_printf_info("Generating cached BDF font...\n"); + + // attempt to open the file + emu_file cachefile(m_manager.machine().options().font_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE); + filerr = cachefile.open(cachedname); + if (filerr) + result = false; + else + { + result = save_cached(cachefile, m_rawsize, hash); + if (!result) + cachefile.remove_on_close(); + } + } else m_rawdata.clear(); @@ -1299,7 +1247,7 @@ bool render_font::load_bdf() { LOG("render_font::load_bdf: ignoring character with negative x advance\n"); } - else if ((256 * ARRAY_LENGTH(m_glyphs)) <= encoding) + else if ((256 * std::size(m_glyphs)) <= encoding) { LOG("render_font::load_bdf: ignoring character with encoding outside range\n"); } @@ -1331,7 +1279,7 @@ bool render_font::load_bdf() // some progress for big fonts if (0 == (++charcount % 256)) - osd_printf_warning("Loading BDF font... (%d characters loaded)\n", charcount); + osd_printf_info("Loading BDF font... (%d characters loaded)\n", charcount); } } @@ -1351,12 +1299,17 @@ bool render_font::load_bdf() // load_cached - load a font in cached format //------------------------------------------------- -bool render_font::load_cached(emu_file &file, u64 length, u32 hash) +bool render_font::load_cached(util::random_read &file, u64 length, u32 hash) { // get the file size, read the header, and check that it looks good - u64 const filesize(file.size()); + u64 filesize; bdc_header header; - if (!header.read(file)) + if (file.length(filesize)) + { + LOG("render_font::load_cached: error determining size of BDC file\n"); + return false; + } + else if (!header.read(file)) { osd_printf_warning("render_font::load_cached: error reading BDC header\n"); return false; @@ -1378,14 +1331,25 @@ bool render_font::load_cached(emu_file &file, u64 length, u32 hash) m_yoffs = header.get_y_offset(); m_defchar = header.get_default_character(); u32 const numchars(header.get_glyph_count()); - if ((file.tell() + (u64(numchars) * bdc_table_entry::size())) > filesize) + u64 filepos; + if (file.tell(filepos)) + { + LOG("render_font::load_cached: failed to determine position in BDC file\n"); + return false; + } + else if ((filepos + (u64(numchars) * bdc_table_entry::size())) > filesize) { LOG("render_font::load_cached: BDC file is too small to hold glyph table\n"); return false; } // now read the rest of the data - u64 const remaining(filesize - file.tell()); + u64 const remaining(filesize - filepos); + if (remaining > std::numeric_limits<std::size_t>::max()) + { + osd_printf_error("render_font::load_cached: BDC file is too large to read into memory\n"); + return false; + } try { m_rawdata.resize(std::size_t(remaining)); @@ -1393,17 +1357,14 @@ bool render_font::load_cached(emu_file &file, u64 length, u32 hash) catch (...) { osd_printf_error("render_font::load_cached: allocation error\n"); + return false; } - for (u64 bytes_read = 0; remaining > bytes_read; ) + auto const [err, bytes] = read(file, &m_rawdata[0], remaining); + if (err || (bytes != remaining)) { - u32 const chunk((std::min)(u64(std::numeric_limits<u32>::max()), remaining)); - if (file.read(&m_rawdata[bytes_read], chunk) != chunk) - { - osd_printf_error("render_font::load_cached: error reading BDC data\n"); - m_rawdata.clear(); - return false; - } - bytes_read += chunk; + osd_printf_error("render_font::load_cached: error reading BDC data\n"); + m_rawdata.clear(); + return false; } // extract the data from the data @@ -1457,16 +1418,8 @@ bool render_font::load_cached(emu_file &file, u64 length, u32 hash) // save_cached - save a font in cached format //------------------------------------------------- -bool render_font::save_cached(const char *filename, u64 length, u32 hash) +bool render_font::save_cached(util::random_write &file, u64 length, u32 hash) { - osd_printf_warning("Generating cached BDF font...\n"); - - // attempt to open the file - emu_file file(m_manager.machine().options().font_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE); - osd_file::error const filerr = file.open(filename); - if (osd_file::error::NONE != filerr) - return false; - // count glyphs unsigned numchars = 0; for (glyph const *const page : m_glyphs) @@ -1481,8 +1434,6 @@ bool render_font::save_cached(const char *filename, u64 length, u32 hash) try { - u32 bytes_written; - { LOG("render_font::save_cached: writing header\n"); bdc_header hdr; @@ -1495,9 +1446,11 @@ bool render_font::save_cached(const char *filename, u64 length, u32 hash) hdr.set_y_offset(m_yoffs); hdr.set_default_character(m_defchar); if (!hdr.write(file)) - throw emu_fatalerror("Error writing cached file"); + throw emu_fatalerror("Error writing cached font file"); } - u64 const table_offs(file.tell()); + u64 table_offs; + if (file.tell(table_offs)) + throw emu_fatalerror("Error writing cached font file"); // allocate an array to hold the character data std::vector<u8> chartable(std::size_t(numchars) * bdc_table_entry::size(), 0); @@ -1506,13 +1459,12 @@ bool render_font::save_cached(const char *filename, u64 length, u32 hash) std::vector<u8> tempbuffer(65536); // write the empty table to the beginning of the file - bytes_written = file.write(&chartable[0], chartable.size()); - if (bytes_written != chartable.size()) - throw emu_fatalerror("Error writing cached file"); + if (write(file, &chartable[0], chartable.size()).first) + throw emu_fatalerror("Error writing cached font file"); // loop over all characters bdc_table_entry table_entry(chartable.empty() ? nullptr : &chartable[0]); - for (unsigned chnum = 0; chnum < (256 * ARRAY_LENGTH(m_glyphs)); chnum++) + for (unsigned chnum = 0; chnum < (256 * std::size(m_glyphs)); chnum++) { if (m_glyphs[chnum / 256] && (0 < m_glyphs[chnum / 256][chnum % 256].width)) { @@ -1531,7 +1483,7 @@ bool render_font::save_cached(const char *filename, u64 length, u32 hash) for (int y = 0; y < gl.bmheight; y++) { int desty = y + m_height + m_yoffs - gl.yoffs - gl.bmheight; - const u32 *src = (desty >= 0 && desty < m_height) ? &gl.bitmap.pix32(desty) : nullptr; + u32 const *const src = (desty >= 0 && desty < m_height) ? &gl.bitmap.pix(desty) : nullptr; for (int x = 0; x < gl.bmwidth; x++) { if (src != nullptr && rgb_t(src[x]).a() != 0) @@ -1550,9 +1502,8 @@ bool render_font::save_cached(const char *filename, u64 length, u32 hash) *dest++ = accum; // write the data - bytes_written = file.write(&tempbuffer[0], dest - &tempbuffer[0]); - if (bytes_written != dest - &tempbuffer[0]) - throw emu_fatalerror("Error writing cached file"); + if (write(file, &tempbuffer[0], dest - &tempbuffer[0]).first) + throw emu_fatalerror("Error writing cached font file"); // free the bitmap and texture m_manager.texture_free(gl.texture); @@ -1575,17 +1526,10 @@ bool render_font::save_cached(const char *filename, u64 length, u32 hash) if (!chartable.empty()) { LOG("render_font::save_cached: writing character table\n"); - file.seek(table_offs, SEEK_SET); - u8 const *bytes(&chartable[0]); - for (u64 remaining = chartable.size(); remaining; ) - { - u32 const chunk((std::min<u64>)(std::numeric_limits<u32>::max(), remaining)); - bytes_written = file.write(bytes, chunk); - if (chunk != bytes_written) - throw emu_fatalerror("Error writing cached file"); - bytes += chunk; - remaining -= chunk; - } + if (file.seek(table_offs, SEEK_SET)) + return false; + if (write(file, &chartable[0], chartable.size()).first) + throw emu_fatalerror("Error writing cached font file"); } // no trouble? @@ -1593,7 +1537,6 @@ bool render_font::save_cached(const char *filename, u64 length, u32 hash) } catch (...) { - file.remove_on_close(); return false; } } @@ -1602,13 +1545,13 @@ bool render_font::save_cached(const char *filename, u64 length, u32 hash) void render_font::render_font_command_glyph() { // FIXME: this is copy/pasta from the BDC loading, and it shouldn't be injected into every font - emu_file file(OPEN_FLAG_READ); - if (file.open_ram(font_uicmd14, sizeof(font_uicmd14)) == osd_file::error::NONE) + util::random_read::ptr file = util::ram_read(font_uicmd14, sizeof(font_uicmd14)); + if (file) { // get the file size, read the header, and check that it looks good - u64 const filesize(file.size()); + u64 const filesize = sizeof(font_uicmd14); bdc_header header; - if (!header.read(file)) + if (!header.read(*file)) { osd_printf_warning("render_font::render_font_command_glyph: error reading BDC header\n"); return; @@ -1623,14 +1566,25 @@ void render_font::render_font_command_glyph() m_height_cmd = header.get_height(); m_yoffs_cmd = header.get_y_offset(); u32 const numchars(header.get_glyph_count()); - if ((file.tell() + (u64(numchars) * bdc_table_entry::size())) > filesize) + u64 filepos; + if (file->tell(filepos)) + { + LOG("render_font::render_font_command_glyph: failed to determine position in BDC file\n"); + return; + } + else if ((filepos + (u64(numchars) * bdc_table_entry::size())) > filesize) { LOG("render_font::render_font_command_glyph: BDC file is too small to hold glyph table\n"); return; } // now read the rest of the data - u64 const remaining(filesize - file.tell()); + u64 const remaining(filesize - filepos); + if (remaining > std::numeric_limits<std::size_t>::max()) + { + osd_printf_error("render_font::render_font_command_glyph: BDC file is too large to read into memory\n"); + return; + } try { m_rawdata_cmd.resize(std::size_t(remaining)); @@ -1638,17 +1592,14 @@ void render_font::render_font_command_glyph() catch (...) { osd_printf_error("render_font::render_font_command_glyph: allocation error\n"); + return; } - for (u64 bytes_read = 0; remaining > bytes_read; ) + auto const [err, bytes] = read(*file, &m_rawdata_cmd[0], remaining); + if (err || (bytes != remaining)) { - u32 const chunk((std::min)(u64(std::numeric_limits<u32>::max()), remaining)); - if (file.read(&m_rawdata_cmd[bytes_read], chunk) != chunk) - { - osd_printf_error("render_font::render_font_command_glyph: error reading BDC data\n"); - m_rawdata_cmd.clear(); - return; - } - bytes_read += chunk; + osd_printf_error("render_font::render_font_command_glyph: error reading BDC data\n"); + m_rawdata_cmd.clear(); + return; } // extract the data from the data |