Пример #1
0
        void 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 = new emu_file(OPEN_FLAG_READ);

            if (!file.open_ram(new MemoryU8(font_uicmd14), (u32)font_uicmd14.Length))
            {
                // get the file size, read the header, and check that it looks good
                u64        filesize = file.size();
                bdc_header header   = new bdc_header();
                if (!header.read(file))
                {
                    osd_printf_warning("render_font::render_font_command_glyph: error reading BDC header\n");
                    file.close();
                    return;
                }
                else if (!header.check_magic() || (bdc_header.MAJVERSION != header.get_major_version()) || (bdc_header.MINVERSION != header.get_minor_version()))
                {
                    LOG("render_font::render_font_command_glyph: incompatible BDC file\n");
                    file.close();
                    return;
                }

                // get global properties from the header
                m_height_cmd = header.get_height();
                m_yoffs_cmd  = header.get_y_offset();
                u32 numchars = header.get_glyph_count();
                if ((file.tell() + ((u64)numchars * bdc_table_entry.size())) > filesize)
                {
                    LOG("render_font::render_font_command_glyph: BDC file is too small to hold glyph table\n");
                    file.close();
                    return;
                }

                // now read the rest of the data
                u64 remaining = filesize - file.tell();
                //try
                {
                    m_rawdata_cmd.resize(remaining);
                }
                //catch (...)
                //{
                //    global.osd_printf_error("render_font::render_font_command_glyph: allocation error\n");
                //}

                for (u64 bytes_read = 0; remaining > bytes_read;)
                {
                    u32 chunk = (u32)std.min(u32.MaxValue, remaining);
                    if (file.read(new Pointer <u8>(m_rawdata_cmd, (int)bytes_read), chunk) != chunk)
                    {
                        osd_printf_error("render_font::render_font_command_glyph: error reading BDC data\n");
                        m_rawdata_cmd.clear();
                        file.close();
                        return;
                    }
                    bytes_read += chunk;
                }

                file.close();

                // extract the data from the data
                size_t          offset = (size_t)numchars * bdc_table_entry.size();
                bdc_table_entry entry  = new bdc_table_entry(m_rawdata_cmd.empty() ? null : new Pointer <u8>(m_rawdata_cmd));
                for (unsigned chindex = 0; chindex < numchars; chindex++, entry = entry.get_next())
                {
                    // if we don't have a subtable yet, make one
                    int chnum = (int)entry.get_encoding();
                    LOG("render_font::render_font_command_glyph: loading character {0}\n", chnum);
                    if (m_glyphs_cmd[chnum / 256] == null)
                    {
                        //try
                        {
                            m_glyphs_cmd[chnum / 256] = new List <glyph>(256);  // new glyph[256];
                            for (int i = 0; i < 256; i++)
                            {
                                m_glyphs_cmd[chnum / 256].Add(new glyph());
                            }
                        }
                        //catch (...)
                        //{
                        //    osd_printf_error("render_font::render_font_command_glyph: allocation error\n");
                        //    m_rawdata_cmd.clear();
                        //    return;
                        //}
                    }

                    // fill in the entry
                    glyph gl = m_glyphs_cmd[chnum / 256][chnum % 256];
                    gl.width    = entry.get_x_advance();
                    gl.xoffs    = entry.get_bb_x_offset();
                    gl.yoffs    = entry.get_bb_y_offset();
                    gl.bmwidth  = entry.get_bb_width();
                    gl.bmheight = entry.get_bb_height();
                    gl.rawdata  = new Pointer <u8>(m_rawdata_cmd, (int)offset);

                    // advance the offset past the character
                    offset += (size_t)((gl.bmwidth * gl.bmheight + 7) / 8);
                    if (m_rawdata_cmd.size() < offset)
                    {
                        osd_printf_verbose("render_font::render_font_command_glyph: BDC file too small to hold all glyphs\n");
                        m_rawdata_cmd.clear();
                        return;
                    }
                }
            }
        }
Пример #2
0
        //-------------------------------------------------
        //  load_cached - load a font in cached format
        //-------------------------------------------------
        bool load_cached(emu_file file, u64 length, u32 hash)
        {
            // get the file size, read the header, and check that it looks good
            u64        filesize = file.size();
            bdc_header header   = new bdc_header();

            if (!header.read(file))
            {
                osd_printf_warning("render_font::load_cached: error reading BDC header\n");
                return(false);
            }
            else if (!header.check_magic() || (bdc_header.MAJVERSION != header.get_major_version()) || (bdc_header.MINVERSION != header.get_minor_version()))
            {
                LOG("render_font::load_cached: incompatible BDC file\n");
                return(false);
            }
            else if (length != 0 && ((header.get_original_length() != length) || (header.get_original_hash() != hash)))
            {
                LOG("render_font::load_cached: BDC file does not match original BDF file\n");
                return(false);
            }

            // get global properties from the header
            m_height  = header.get_height();
            m_scale   = 1.0f / (float)(m_height);
            m_yoffs   = header.get_y_offset();
            m_defchar = header.get_default_character();
            u32 numchars = header.get_glyph_count();

            if (file.tell() + ((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 remaining = filesize - file.tell();

            try
            {
                m_rawdata.resize(remaining);
            }
            catch (Exception)
            {
                osd_printf_error("render_font::load_cached: allocation error\n");
            }
            for (u64 bytes_read = 0; remaining > bytes_read;)
            {
                u32 chunk = (u32)std.min(u32.MaxValue, remaining);
                if (file.read(new Pointer <u8>(m_rawdata, (int)bytes_read), chunk) != chunk)  //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;
            }

            // extract the data from the data
            size_t          offset = (size_t)numchars * bdc_table_entry.size();
            bdc_table_entry entry  = new bdc_table_entry(m_rawdata.empty() ? null : new Pointer <u8>(m_rawdata));

            for (unsigned chindex = 0; chindex < numchars; chindex++, entry = entry.get_next())
            {
                // if we don't have a subtable yet, make one
                int chnum = (int)entry.get_encoding();
                LOG("render_font::load_cached: loading character {0}\n", chnum);
                if (m_glyphs[chnum / 256] == null || m_glyphs[chnum / 256].Count == 0)
                {
                    //try
                    {
                        m_glyphs[chnum / 256] = new List <glyph>(256);  // new glyph[256];
                        for (int i = 0; i < 256; i++)
                        {
                            m_glyphs[chnum / 256].Add(new glyph());
                        }
                    }
                    //catch (Exception )
                    //{
                    //    global.osd_printf_error("render_font::load_cached: allocation error\n");
                    //    m_rawdata.clear();
                    //    return false;
                    //}
                }

                // fill in the entry
                glyph gl = m_glyphs[chnum / 256][chnum % 256];
                gl.width    = entry.get_x_advance();
                gl.xoffs    = entry.get_bb_x_offset();
                gl.yoffs    = entry.get_bb_y_offset();
                gl.bmwidth  = entry.get_bb_width();
                gl.bmheight = entry.get_bb_height();
                gl.rawdata  = new Pointer <u8>(m_rawdata, (int)offset);

                // advance the offset past the character
                offset += (size_t)((gl.bmwidth * gl.bmheight + 7) / 8);
                if (m_rawdata.size() < offset)
                {
                    osd_printf_verbose("render_font::load_cached: BDC file too small to hold all glyphs\n");
                    m_rawdata.clear();
                    return(false);
                }
            }

            // got everything
            m_format = format.CACHED;
            return(true);
        }