Giter Club home page Giter Club logo

Comments (9)

bwdalmijn avatar bwdalmijn commented on August 16, 2024 1

PHP font files, by converting the truetype font files via this site

from fpdf2.

Lucas-C avatar Lucas-C commented on August 16, 2024

I'm waiting for the clean-up in this PR to be merged: #22

After that I'll give a look at this.
A good start would be to make our CharmapTest.test_first_999_chars test (in test/end_to_end_legacy/charmap/charmap_test.py) pass.

from fpdf2.

bwdalmijn avatar bwdalmijn commented on August 16, 2024

Hello, i somewhat bypassed this by taking the php files and parsing them myself. I implemented the new code concerning the truetype font files, it "dies" over the version of the ttf file. If i remove it , it says there is no attribute "name" in the extracted information. If you want i could drop the code of the php parsing here somewhere. I also modified the add_font function to accomodate this.

from fpdf2.

Lucas-C avatar Lucas-C commented on August 16, 2024

I'm curious about reading your code, so yes! :)

I'm not sure about what are the PHP files you are refering to though.

from fpdf2.

bwdalmijn avatar bwdalmijn commented on August 16, 2024

Sorry, posting the code went a bit wrong...

from fpdf2.

bwdalmijn avatar bwdalmijn commented on August 16, 2024
import re
import regex

def parse_php(fontfile):
    font_dict = {}
    for item in php_chunks(fontfile):
        key, attr = item.split(" = ")
        attr = attr.replace("\t","").strip()
        attr = re.sub("^(.*);",r"\1",attr)
        # re.split("[,](?!'=>)",data["cw"])
        if re.match("'(.*)'",attr):
            attr = re.sub("'(.*)'",r"\1",attr)
        try:
            attr = eval(attr)
            font_dict[key.replace("$","").strip()] = attr
        except:            
            if "array" in attr:
                if re.match("^array\(",attr):
                    attr_dict = {}
                    attr = re.sub("array\((.*)\)",r"\1",attr)
                    attr = regex.split("(?<!array\(\d*)[,](?!'=>)",attr)
                    for row in attr:
                        dict_key, dict_item = row.strip().split("=>")
                        try:
                            attr_dict[str(eval(dict_key))] = eval(dict_item)
                        except:
                            attr_dict[str(eval(dict_key))] = dict_item
                    font_dict[key.replace("$","").strip()] = attr_dict
            else:
                font_dict[key.replace("$","").strip()] = attr
    return font_dict    
    
def php_chunks(raw):
    raw = raw.read()
    chunk = ""
    for idx, line in enumerate(raw.splitlines()):
        if line.startswith("$"):
            if idx != 1:
                yield chunk
            chunk = ""
            chunk = "".join(line)
        else:
            chunk = "".join([chunk,line])
    
    
if __name__ == "__main__":
    fontfile = open("calibrib.php","r")
    data = parse_php(fontfile)

from fpdf2.

bwdalmijn avatar bwdalmijn commented on August 16, 2024
def add_font(self, family, style = '', fname = None, file_type = "uni"):
        "Add a TrueType or Type1 font"
        family = family.lower()
        if not fname:
            fname = family.replace(' ', '') + style.lower() + '.pkl'

        if (family == 'arial'): family = 'helvetica'
        style = style.upper()
        if (style == 'IB'): style = 'BI'
        fontkey = family + style

        # Font already added
        if fontkey in self.fonts: return
        if file_type=="uni":
            global SYSTEM_TTFONTS, FPDF_CACHE_MODE, FPDF_CACHE_DIR
            if os.path.exists(fname):
                ttffilename = fname
            elif (FPDF_FONT_DIR and
                  os.path.exists(os.path.join(FPDF_FONT_DIR, fname))):
                ttffilename = os.path.join(FPDF_FONT_DIR, fname)
            elif (SYSTEM_TTFONTS and
                  os.path.exists(os.path.join(SYSTEM_TTFONTS, fname))):
                ttffilename = os.path.join(SYSTEM_TTFONTS, fname)
            else:
                raise RuntimeError("TTF Font file not found: %s" % fname)
            name = ''  # noqa: F841
            if FPDF_CACHE_MODE == 0:
                unifilename = os.path.splitext(ttffilename)[0] + '.pkl'
            elif FPDF_CACHE_MODE == 2:
                unifilename = os.path.join(FPDF_CACHE_DIR,
                    _hashpath(ttffilename) + ".pkl")
            else:
                unifilename = None

            font_dict = load_cache(unifilename)
            if font_dict is None:
                ttf = TTFontFile()
                ttf.getMetrics(ttffilename)
                desc = {
                    'Ascent'       : int(round(ttf.ascent, 0)),
                    'Descent'      : int(round(ttf.descent, 0)),
                    'CapHeight'    : int(round(ttf.capHeight, 0)),
                    'Flags'        : ttf.flags,
                    'FontBBox'     : "[%s %s %s %s]" % (
                        int(round(ttf.bbox[0], 0)),
                        int(round(ttf.bbox[1], 0)),
                        int(round(ttf.bbox[2], 0)),
                        int(round(ttf.bbox[3], 0))),
                    'ItalicAngle'  : int(ttf.italicAngle),
                    'StemV'        : int(round(ttf.stemV, 0)),
                    'MissingWidth' : int(round(ttf.defaultWidth, 0)),
                }

                # Generate metrics .pkl file
                font_dict = {
                    'name'         : re.sub('[ ()]', '', ttf.fullName),
                    'type'         : 'TTF',
                    'desc'         : desc,
                    'up'           : round(ttf.underlinePosition),
                    'ut'           : round(ttf.underlineThickness),
                    'ttffile'      : ttffilename,
                    'fontkey'      : fontkey,
                    'originalsize' : os.stat(ttffilename).st_size,
                    'cw'           : ttf.charWidths,
                }

                if unifilename:
                    try:
                        with open(unifilename, "wb") as fh:
                            pickle.dump(font_dict, fh)
                    except IOError as e:
                        if not e.errno == errno.EACCES:
                            raise  # Not a permission error.
                del ttf

            # include numbers in the subset! (if alias present)
            have_page_alias = lambda: hasattr(self, 'str_alias_nb_pages')
            sbarr = list(range(0, 57 if have_page_alias() else 32))

            self.fonts[fontkey] = {
                'i'           : len(self.fonts) + 1,
                'type'        : font_dict['type'],
                'name'        : font_dict['name'],
                'desc'        : font_dict['desc'],
                'up'          : font_dict['up'],
                'ut'          : font_dict['ut'],
                'cw'          : font_dict['cw'],
                'ttffile'     : font_dict['ttffile'],
                'fontkey'     : fontkey,
                'subset'      : sbarr,
                'unifilename' : unifilename
            }
            self.font_files[fontkey] = {'length1': font_dict['originalsize'],
                                        'type': "TTF", 'ttffile': ttffilename}
            self.font_files[fname]   = {'type': "TTF"}
        elif file_type=="pickled":
            with open(fname, 'rb') as fontfile:
                font_dict = pickle.load(fontfile)
            self.fonts[fontkey] = {'i': len(self.fonts) + 1}
            self.fonts[fontkey].update(font_dict)
            diff = font_dict.get('diff')
            if (diff):
                # Search existing encodings
                d  = 0
                nb = len(self.diffs)
                for i in range(1, nb + 1):
                    if (self.diffs[i] == diff):
                        d = i
                        break
                if (d == 0):
                    d = nb + 1
                    self.diffs[d] = diff
                self.fonts[fontkey]['diff'] = d
            filename = font_dict.get('filename')
            if (filename):
                if (font_dict['type'] == 'TrueType'):
                    originalsize = font_dict['originalsize']
                    self.font_files[filename] = {'length1': originalsize}
                else:
                    self.font_files[filename] = {'length1': font_dict['size1'],
                                                 'length2': font_dict['size2']}
        elif file_type=="php":
            if os.path.exists(os.path.join(FPDF_FONT_DIR,fname)):
                phpfilename = os.path.join(FPDF_FONT_DIR,fname)
            elif os.path.exists(fname):
                phpfilename = fname
                if not os.path.exists(os.path.join(FPDF_FONT_DIR,os.path.basename(fname))):
                    shutil.copy2(fname,os.path.join(FPDF_FONT_DIR,os.path.basename(fname)))
                    z_file = re.sub(".php",".z",fname)
                    shutil.copy2(z_file,os.path.join(FPDF_FONT_DIR,os.path.basename(z_file)))
            else:
                raise RuntimeError("PHP Font file not found: %s" % fname)
            with open(phpfilename,'r') as fontfile:
                font_dict = parse_php(fontfile)
            self.fonts[fontkey] = {'i': len(self.fonts) + 1}
            self.fonts[fontkey].update(font_dict)
            filename = font_dict.get('file')
            if (filename):
                if (font_dict['type'] == 'TrueType'):
                    self.font_files[filename] = {'length1': font_dict['originalsize'],
                                                'type': font_dict["type"],
                                                'file': font_dict["file"]}
                else:
                    self.font_files[filename] = {'length1': font_dict['size1'],
                                                 'length2': font_dict['size2']}

from fpdf2.

bwdalmijn avatar bwdalmijn commented on August 16, 2024

It is not pretty, but it does allow me to use other fonts.

from fpdf2.

Lucas-C avatar Lucas-C commented on August 16, 2024

Thank you @bwdalmijn Interesting, and I was able to find the source code behind this /makefont/ web page.

I think I found a simpler fix for this issue though: #26

from fpdf2.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.