# -*- encoding: utf-8; frozen_string_literal: true -*-
#
#--
# This file is part of HexaPDF.
#
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
# Copyright (C) 2014-2021 Thomas Leitner
#
# HexaPDF is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License version 3 as
# published by the Free Software Foundation with the addition of the
# following permission added to Section 15 as permitted in Section 7(a):
# FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
# THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
# INFRINGEMENT OF THIRD PARTY RIGHTS.
#
# HexaPDF is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with HexaPDF. If not, see .
#
# The interactive user interfaces in modified source and object code
# versions of HexaPDF must display Appropriate Legal Notices, as required
# under Section 5 of the GNU Affero General Public License version 3.
#
# In accordance with Section 7(b) of the GNU Affero General Public
# License, a covered work must retain the producer line in every PDF that
# is created or manipulated using HexaPDF.
#
# If the GNU Affero General Public License doesn't fit your need,
# commercial licenses are available at .
#++
require 'hexapdf/stream'
require 'hexapdf/font/cmap'
module HexaPDF
module Type
# Represents a generic font object.
#
# This class is the base class for all font objects, be it simple fonts or composite fonts.
class Font < Dictionary
define_type :Font
define_field :Type, type: Symbol, required: true, default: type
define_field :ToUnicode, type: Stream, version: '1.2'
# Retrieves the font wrapper that is needed when this font is used for text output. Returns
# +nil+ if this font can't be used for text output.
#
# Note: For internal use only!
#
# See: HexaPDF::Font
def font_wrapper
@font_wrapper ||= nil
end
# Sets the font wrapper.
#
# See: #font_wrapper
def font_wrapper=(font)
@font_wrapper = font
end
# Font objects must always be indirect.
def must_be_indirect?
true
end
# Returns the UTF-8 string for the given character code, or calls the configuration option
# 'font.on_missing_unicode_mapping' if no mapping was found.
def to_utf8(code)
to_unicode_cmap&.to_unicode(code) || missing_unicode_mapping(code)
end
# Returns the bounding box of the font or +nil+ if it is not found.
def bounding_box
if key?(:FontDescriptor) && self[:FontDescriptor].key?(:FontBBox)
self[:FontDescriptor][:FontBBox].value
else
nil
end
end
# Returns +true+ if the font is embedded.
def embedded?
dict = self[:FontDescriptor]
dict && (dict[:FontFile] || dict[:FontFile2] || dict[:FontFile3])
end
# Returns the embeeded font file object or +nil+ if the font is not embedded.
def font_file
embedded?
end
# Returns the glyph scaling factor for transforming from glyph space to text space.
def glyph_scaling_factor
0.001
end
private
# Parses and caches the ToUnicode CMap.
def to_unicode_cmap
cache(:to_unicode_cmap) do
if key?(:ToUnicode)
HexaPDF::Font::CMap.parse(self[:ToUnicode].stream)
else
nil
end
end
end
# Calls the configured proc for handling missing unicode mappings.
def missing_unicode_mapping(code)
@document.config['font.on_missing_unicode_mapping'].call(code, self)
end
end
end
end