Exemple #1
0
    public override void SetCount()
    {
        scale = frame.distance / 3;

        scaledPadding       = scale * padding;
        scaledCharacterSize = scale * characterSize;
        scaledLineHeight    = scale * lineHeight;

        //count = text.length
        glyphs = new List <glyph>();

        count = 0;

        string[] words = text.Split(' ');


        int   column = 0;
        int   row    = 0;
        float value  = scaledPadding * 3;

        foreach (string word in words)
        {
            char[] letters = word.ToCharArray();
            if (value + letters.Length * scaledCharacterSize >= frame.width - scaledPadding)
            {
                row++;
                value  = scaledPadding;
                column = 0;
            }

            foreach (char c in letters)
            {
                glyph g = new glyph(column, row, count, c);
                glyphs.Add(g);
                value += scaledCharacterSize;
                column++;
                count++;
                //print((int)c);
                //print(column);
            }

            column++;
            value += scaledCharacterSize;
        }

        //print(words[0]);
    }
Exemple #2
0
        // texture/bitmap queries

        //-------------------------------------------------
        //  get_char_texture_and_bounds - return the
        //  texture for a character and compute the
        //  bounds of the final bitmap
        //-------------------------------------------------
        public render_texture get_char_texture_and_bounds(float height, float aspect, char32_t chnum, ref render_bounds bounds)
        {
            glyph gl = get_char(chnum);

            // on entry, assume x0,y0 are the top,left coordinate of the cell and add
            // the character bounding box to that position
            float scale = m_scale * height;

            bounds.x0 += (float)gl.xoffs * scale * aspect;

            // compute x1,y1 from there based on the bitmap size
            bounds.x1 = bounds.x0 + (float)gl.bmwidth * scale * aspect;
            bounds.y1 = bounds.y0 + (float)m_height * scale;

            // return the texture
            return(gl.texture);
        }
Exemple #3
0
        private static void drawLetterSVGFont(double scale, string actualCharString)
        {   // https://gitlab.com/oskay/svg-fonts
            // <missing-glyph horiz-adv-x="378" />
            // <glyph unicode="!" glyph-name="exclam" horiz-adv-x="359" d="M 444 665 L 403 592 L 295 362 L 232 214 M 204 63 L 182 40.9" />
            //Logger.Trace("drawLetterSVGFont");
            scale = gcHeight / (21 * 31.52);   //=661.92 factor_Em2Px = 150; scale = 0.0254    *1000 = 25,4

            glyph tmpGlyph = null;

            if (svgGlyphs.ContainsKey(actualCharString))
            {
                //Logger.Trace("drawLetterSVGFont '{0}'", actualCharString);
                tmpGlyph = svgGlyphs[actualCharString];
            }
            else if (svgGlyphs.ContainsKey("missing-glyph"))
            {
                Logger.Trace("drawLetterSVGFont 'missing - glyph'");
                tmpGlyph = svgGlyphs["missing-glyph"];
            }
            else
            {
                Logger.Error("Glyph not found");
                return;
            }

            //       var tmpX = offsetX;// + tmpGlyph.x * scale;
            if (tmpGlyph.d.Length > 0)
            {
                string separators = @"(?=[A-Za-z])";
                var    tokens     = Regex.Split(tmpGlyph.d, separators).Where(t => !string.IsNullOrEmpty(t));
                int    token_cnt  = 0;
                foreach (string token in tokens)
                {
                    drawToken(token, offsetX + gcOffX, offsetY + gcOffY, scale, token_cnt++, false);
                }
            }
            offsetX   += tmpGlyph.x * scale + gcFontDistance; //double.Parse(svgsplit[1]) * scale + gcFontDistance;
            isSameWord = true;
        }
Exemple #4
0
        //-------------------------------------------------
        //  get_scaled_bitmap_and_bounds - return a
        //  scaled bitmap and bounding rect for a char
        //-------------------------------------------------
        public void get_scaled_bitmap_and_bounds(bitmap_argb32 dest, float height, float aspect, char32_t chnum, out rectangle bounds)
        {
            bounds = default;

            glyph gl = get_char(chnum);

            // on entry, assume x0,y0 are the top,left coordinate of the cell and add
            // the character bounding box to that position
            float scale = m_scale * height;

            bounds.min_x = (int)((float)(gl.xoffs) * scale * aspect);
            bounds.min_y = 0;

            // compute x1,y1 from there based on the bitmap size
            bounds.set_width((int)((float)(gl.bmwidth) * scale * aspect));
            bounds.set_height((int)((float)(m_height) * scale));

            // if the bitmap isn't big enough, bail
            if (dest.width() < bounds.width() || dest.height() < bounds.height())
            {
                return;
            }

            // if no texture, fill the target
            if (gl.texture == null)
            {
                dest.fill(0);
                return;
            }

            throw new emu_unimplemented();
#if false
            // scale the font
            bitmap_argb32 tempbitmap = new bitmap_argb32(&dest.pix(0), bounds.width(), bounds.height(), dest.rowpixels());
            render_texture.hq_scale(tempbitmap, gl.bitmap, gl.bitmap.cliprect(), null);
#endif
        }
Exemple #5
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;
                    }
                }
            }
        }
Exemple #6
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);
        }
Exemple #7
0
        //-------------------------------------------------
        //  char_expand - expand the raw data for a
        //  character into a bitmap
        //-------------------------------------------------
        void char_expand(char32_t chnum, glyph gl)
        {
            LOG("render_font::char_expand: expanding character {0}\n", chnum);

            rgb_t fgcol  = (gl.color != 0 ? gl.color : new rgb_t(0xff, 0xff, 0xff, 0xff));
            rgb_t bgcol  = new rgb_t(0x00, 0xff, 0xff, 0xff);
            bool  is_cmd = ((chnum >= COMMAND_UNICODE) && (chnum < COMMAND_UNICODE + MAX_GLYPH_FONT));

            if (is_cmd)
            {
                throw new emu_unimplemented();
#if false
                // punt if nothing there
                if (gl.bmwidth == 0 || gl.bmheight == 0 || gl.rawdata == null)
                {
                    return;
                }

                // allocate a new bitmap of the size we need
                gl.bitmap.allocate(gl.bmwidth, m_height_cmd);
                gl.bitmap.fill(0);

                // extract the data
                const char *ptr      = gl.rawdata;
                byte        accum    = 0;
                byte        accumbit = 7;
                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.pix(desty, 0) : nullptr;
                    {
                        for (int x = 0; x < gl.bmwidth; x++)
                        {
                            if (accumbit == 7)
                            {
                                accum = *ptr++;
                            }
                            if (dest != null)
                            {
                                *dest++ = (accum & (1 << accumbit)) ? color : rgb_t(0x00, 0xff, 0xff, 0xff);
                            }
                            accumbit = (accumbit - 1) & 7;
                        }
                    }
                }
#endif
            }
            else if (m_format == format.OSD)
            {
                throw new emu_unimplemented();
#if false
                // if we're an OSD font, query the info
#endif
            }
            else if (gl.bmwidth == 0 || gl.bmheight == 0 || gl.rawdata == null)
            {
                // abort if nothing there
                LOG("render_font::char_expand: empty bitmap bounds or no raw data\n");
                return;
            }
            else
            {
                // other formats need to parse their data
                LOG("render_font::char_expand: building bitmap from raw data\n");

                // allocate a new bitmap of the size we need
                gl.bitmap.allocate(gl.bmwidth, m_height);
                gl.bitmap.fill(0);

                // extract the data
                Pointer <u8> ptr      = new Pointer <u8>(gl.rawdata); //const char *ptr = gl.rawdata;
                u8           accum    = 0;
                u8           accumbit = 7;
                for (int y = 0; y < gl.bmheight; y++)
                {
                    int        desty = y + m_height + m_yoffs - gl.yoffs - gl.bmheight;
                    PointerU32 dest  = ((0 <= desty) && (m_height > desty)) ? gl.bitmap.pix(desty) : null; //u32 *dest(((0 <= desty) && (m_height > desty)) ? &gl.bitmap.pix(desty) : nullptr);

                    if (m_format == format.TEXT)
                    {
                        if (dest != null)
                        {
                            for (int x = 0; gl.bmwidth > x;)
                            {
                                // scan for the next hex digit
                                int bits = -1;
                                while ('\r' != ptr[0] && '\n' != ptr[0] && 0 > bits)  // while (('\r' != *ptr) && ('\n' != *ptr) && (0 > bits))
                                {
                                    if (ptr[0] >= '0' && ptr[0] <= '9')
                                    {
                                        bits = ptr[0] - '0';  //bits = *ptr++ - '0';
                                        ptr++;
                                    }
                                    else if (ptr[0] >= 'A' && ptr[0] <= 'F')
                                    {
                                        bits = ptr[0] - 'A' + 10;
                                        ptr++;
                                    }
                                    else if (ptr[0] >= 'a' && ptr[0] <= 'f')
                                    {
                                        bits = ptr[0] - 'a' + 10;
                                        ptr++;
                                    }
                                    else
                                    {
                                        ptr++;
                                    }
                                }

                                // expand the four bits
                                dest[0] = (bits & 8) != 0 ? fgcol : bgcol;  dest++;  //*dest++ = (bits & 8) ? fgcol : bgcol;
                                if (gl.bmwidth > ++x)
                                {
                                    dest[0] = (bits & 4) != 0 ? fgcol : bgcol;  dest++;
                                }                                                            //*dest++ = (bits & 4) ? fgcol : bgcol;
                                if (gl.bmwidth > ++x)
                                {
                                    dest[0] = (bits & 2) != 0 ? fgcol : bgcol;  dest++;
                                }                                                            //*dest++ = (bits & 2) ? fgcol : bgcol;
                                if (gl.bmwidth > ++x)
                                {
                                    dest[0] = (bits & 1) != 0 ? fgcol : bgcol;  dest++;
                                }                                                            //*dest++ = (bits & 1) ? fgcol : bgcol;

                                x++;
                            }

                            // advance to the next line
                            ptr = next_line(ptr);
                        }
                    }
                    else if (m_format == format.CACHED)
                    {
                        for (int x = 0; x < gl.bmwidth; x++)
                        {
                            if (accumbit == 7)
                            {
                                accum = ptr[0];
                                ptr++;
                            }

                            if (dest != null)
                            {
                                dest[0] = (accum & (1 << accumbit)) != 0 ? fgcol : bgcol;  dest++;
                            }                                                                           //*dest++ = (accum & (1 << accumbit)) ? fgcol : bgcol;

                            accumbit = (u8)((accumbit - 1) & 7);
                        }
                    }
                }
            }

            // wrap a texture around the bitmap
            gl.texture = m_manager.texture_alloc(render_texture.hq_scale);
            gl.texture.set_bitmap(gl.bitmap, gl.bitmap.cliprect(), texture_format.TEXFORMAT_ARGB32);
        }
Exemple #8
0
        // helpers
        //-------------------------------------------------
        //  get_char - return a pointer to a character
        //  in a font, expanding if necessary
        //-------------------------------------------------
        glyph get_char(char32_t chnum)
        {
            unsigned page = chnum / 256;

            if (page >= m_glyphs.Length)
            {
                if ((0 <= m_defchar) && (chnum != m_defchar))
                {
                    return(get_char((char32_t)m_defchar));
                }
                else
                {
                    return(get_char_dummy_glyph);
                }
            }
            else if (m_glyphs[page] == null || m_glyphs[page].Count == 0)
            {
                //mamep: make table for command glyph
                if ((m_format == format.OSD) || ((chnum >= COMMAND_UNICODE) && (chnum < COMMAND_UNICODE + MAX_GLYPH_FONT)))
                {
                    m_glyphs[page] = new List <glyph>(256);  // new glyph[256];
                    for (int i = 0; i < 256; i++)
                    {
                        m_glyphs[page].Add(new glyph());
                    }
                }
                else if ((0 <= m_defchar) && (chnum != m_defchar))
                {
                    return(get_char((char32_t)m_defchar));
                }
                else
                {
                    return(get_char_dummy_glyph);
                }
            }

            // if the character isn't generated yet, do it now
            glyph gl = m_glyphs[page][(int)(chnum % 256)];

            if (!gl.bitmap.valid())
            {
                //mamep: command glyph support
                if (m_height_cmd != 0 && chnum >= COMMAND_UNICODE && chnum < COMMAND_UNICODE + MAX_GLYPH_FONT)
                {
                    glyph glyph_ch = m_glyphs_cmd[page][(int)(chnum % 256)];
                    float scale    = (float)m_height / (float)m_height_cmd;
                    if (m_format == format.OSD)
                    {
                        scale *= 0.90f;
                    }

                    if (!glyph_ch.bitmap.valid())
                    {
                        char_expand(chnum, glyph_ch);
                    }

                    //mamep: for color glyph
                    gl.color = glyph_ch.color;

                    gl.width    = (int)(glyph_ch.width * scale + 0.5f);
                    gl.xoffs    = (int)(glyph_ch.xoffs * scale + 0.5f);
                    gl.yoffs    = (int)(glyph_ch.yoffs * scale + 0.5f);
                    gl.bmwidth  = (int)(glyph_ch.bmwidth * scale + 0.5f);
                    gl.bmheight = (int)(glyph_ch.bmheight * scale + 0.5f);

                    gl.bitmap.allocate(gl.bmwidth, gl.bmheight);
                    rectangle clip = new rectangle(
                        0, glyph_ch.bitmap.width() - 1,
                        0, glyph_ch.bitmap.height() - 1);
                    render_texture.hq_scale(gl.bitmap, glyph_ch.bitmap, clip, null);

                    /* wrap a texture around the bitmap */
                    gl.texture = m_manager.texture_alloc(render_texture.hq_scale);
                    gl.texture.set_bitmap(gl.bitmap, gl.bitmap.cliprect(), texture_format.TEXFORMAT_ARGB32);
                }
                else
                {
                    char_expand(chnum, gl);
                }
            }

            return(gl);
        }
Exemple #9
0
    public void MakeGlyphs(string parsedText)
    {
        string[] words = parsedText.Split(' ');


        int first = 0;

        foreach (string word in words)
        {
            // makes sure we skip the first space of the section
            if (first != 0)
            {
                column++;
                locationX += scaledAdvance;
            }
            else
            {
                first = 1;
            }


            char[] letters = word.ToCharArray();



            float newLine   = 0;
            float wordWidth = 0;
            foreach (char c in letters)
            {
                if (c == '\n')
                {
                }
                else
                {
                    wordWidth += scaledAdvance;// * scale
                }
            }

            if (locationX + wordWidth >= frame.width - scaledPadding * 2)
            {
                row++;
                locationY += scaledLineHeight;
                locationX  = scaledPadding;
                column     = 0;
            }


            foreach (char c in letters)
            {
                if (c == '\n')
                {
                    row++;
                    locationY += scaledLineHeight;
                    locationX  = scaledPadding;
                    column     = 0;
                }
                else
                {
                    if (NovaMono.info.ContainsKey(c))
                    {
                        float[] v1 = NovaMono.info[c];


                        // print( c );
                        glyph g = new glyph(locationX, locationY, count, v1, currentTextureVal, currentScaleOffset, currentHueOffset, currentSpecial);
                        glyphs.Add(g);



                        locationX += scaledAdvance;
                        column++;
                        count++;
                    }
                    else
                    {
                        DebugThis("character not found");
                        print(c);
                        print(row);
                        print(column);
                    }
                }
            }
        }
    }