-
-
Notifications
You must be signed in to change notification settings - Fork 146
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f5b4964
commit ccc2130
Showing
358 changed files
with
1,405 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
borb version 2.0.29 | ||
borb version 2.0.30 | ||
Joris Schellekens |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
""" | ||
This file is part of the borb (R) project. | ||
Copyright (c) 2020-2040 borb Group NV | ||
Authors: Joris Schellekens, et al. | ||
This program 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 | ||
BORB GROUP. BORB GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT | ||
OF THIRD PARTY RIGHTS | ||
This program 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 this program; if not, see http://www.gnu.org/licenses or write to | ||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
Boston, MA, 02110-1301 USA. | ||
The interactive user interfaces in modified source and object code versions | ||
of this program must display Appropriate Legal Notices, as required under | ||
Section 5 of the GNU Affero General Public License. | ||
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 borb. | ||
You can be released from the requirements of the license by purchasing | ||
a commercial license. Buying such a license is mandatory as soon as you | ||
develop commercial activities involving the borb software without | ||
disclosing the source code of your own applications. | ||
These activities include: offering paid services to customers as an ASP, | ||
serving PDFs on the fly in a web application, shipping borb with a closed | ||
source product. | ||
For more information, please contact borb Software Corp. at this | ||
address: [email protected] | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
""" | ||
This implementation of WriteBaseTransformer is responsible for determining which characters (typing.Set[str]) | ||
are used by which Font. This is particularly useful when performing Font subsetting. | ||
""" | ||
import typing | ||
|
||
from borb.pdf.canvas.event.chunk_of_text_render_event import ChunkOfTextRenderEvent | ||
from borb.pdf.canvas.event.event_listener import EventListener, Event | ||
from borb.pdf.canvas.font.font import Font | ||
|
||
|
||
class CharacterSetListener(EventListener): | ||
""" | ||
This implementation of WriteBaseTransformer is responsible for determining which characters (typing.Set[str]) | ||
are used by which Font. This is particularly useful when performing Font subsetting. | ||
""" | ||
|
||
def __init__(self): | ||
super(CharacterSetListener, self).__init__() | ||
self._character_set_per_font: typing.Dict[Font, typing.Set[str]] = {} | ||
|
||
def _event_occurred(self, event: Event) -> None: | ||
if isinstance(event, ChunkOfTextRenderEvent): | ||
f: Font = event.get_font() | ||
if f in self._character_set_per_font: | ||
s: typing.Set[str] = self._character_set_per_font[f] | ||
for c in event.get_text(): | ||
s.add(c) | ||
self._character_set_per_font[f] = s | ||
else: | ||
self._character_set_per_font[f] = set([x for x in event.get_text()]) | ||
|
||
def get_character_set_per_font(self) -> typing.Dict[Font, typing.Set[str]]: | ||
""" | ||
This function returns the character set (typing.Set[str]) used by each Font | ||
:return: the character set used by each Font | ||
""" | ||
return self._character_set_per_font |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
""" | ||
This CanvasOperator copies an existing operator and writes its bytes to a content stream of the canvas. | ||
""" | ||
import typing | ||
from decimal import Decimal | ||
|
||
from borb.io.read.types import AnyPDFType, HexadecimalString, String, Name | ||
from borb.pdf.canvas.operator.canvas_operator import CanvasOperator | ||
|
||
|
||
class CopyCommandOperator(CanvasOperator): | ||
""" | ||
This CanvasOperator copies an existing operator and writes its bytes to a content stream of the canvas. | ||
""" | ||
|
||
def __init__( | ||
self, operator_to_copy: CanvasOperator, output_content_stream: bytearray | ||
): | ||
super().__init__("", 0) | ||
self._operator_to_copy = operator_to_copy | ||
self._output_content_stream: bytearray = output_content_stream | ||
|
||
def get_text(self) -> str: | ||
""" | ||
Return the str that invokes this CanvasOperator | ||
""" | ||
return self._operator_to_copy.get_text() | ||
|
||
def get_number_of_operands(self) -> int: | ||
""" | ||
Return the number of operands for this CanvasOperator | ||
""" | ||
return self._operator_to_copy.get_number_of_operands() | ||
|
||
def _operand_to_str(self, op: AnyPDFType) -> str: | ||
if isinstance(op, Decimal): | ||
return str(op) | ||
if isinstance(op, HexadecimalString): | ||
return "<" + op._text + ">" | ||
if isinstance(op, String): | ||
return "(" + op._text + ")" | ||
if isinstance(op, Name): | ||
return "/" + str(op) | ||
if isinstance(op, list): | ||
return "[" + "".join([self._operand_to_str(x) + " " for x in op])[:-1] + "]" | ||
return "" | ||
|
||
def invoke( | ||
self, | ||
canvas_stream_processor: "CanvasStreamProcessor", # type: ignore [name-defined] | ||
operands: typing.List[AnyPDFType] = [], | ||
event_listeners: typing.List["EventListener"] = [], # type: ignore [name-defined] | ||
) -> None: | ||
""" | ||
Invokes this CanvasOperator | ||
""" | ||
|
||
# execute command | ||
self._operator_to_copy.invoke(canvas_stream_processor, operands) | ||
|
||
# copy command in content stream | ||
canvas = canvas_stream_processor.get_canvas() | ||
|
||
# copy operand string | ||
self._output_content_stream += b"\n" | ||
self._output_content_stream += b"".join( | ||
[(bytes(self._operand_to_str(s), encoding="utf8") + b" ") for s in operands] | ||
) | ||
self._output_content_stream += bytes(self.get_text(), encoding="utf8") |
105 changes: 105 additions & 0 deletions
105
borb/io/write/font/subset_show_text_with_glyph_positioning.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
""" | ||
Show one or more text strings, allowing individual glyph positioning. Each | ||
element of array shall be either a string or a number. | ||
""" | ||
import typing | ||
from decimal import Decimal | ||
from typing import List | ||
|
||
from borb.io.read.types import AnyPDFType, Name, String, HexadecimalString | ||
from borb.io.write.font.copy_command_operator import CopyCommandOperator | ||
from borb.pdf.canvas.font.font import Font | ||
from borb.pdf.canvas.operator.text.show_text_with_glyph_positioning import ( | ||
ShowTextWithGlyphPositioning, | ||
) | ||
|
||
|
||
class SubSetShowTextWithGlyphPositioning(CopyCommandOperator): | ||
""" | ||
Show one or more text strings, allowing individual glyph positioning. Each | ||
element of array shall be either a string or a number. If the element is a | ||
string, this operator shall show the string. If it is a number, the operator | ||
shall adjust the text position by that amount; that is, it shall translate the | ||
text matrix, T . The number shall be expressed in thousandths of a unit | ||
mof text space (see 9.4.4, "Text Space Details"). This amount shall be | ||
subtracted from the current horizontal or vertical coordinate, depending | ||
on the writing mode. In the default coordinate system, a positive | ||
adjustment has the effect of moving the next glyph painted either to the | ||
left or down by the given amount. Figure 46 shows an example of the | ||
effect of passing offsets to TJ. | ||
""" | ||
|
||
def __init__( | ||
self, old_fonts: typing.List[Font], new_fonts: typing.List[Font], s: bytearray | ||
): | ||
super(SubSetShowTextWithGlyphPositioning, self).__init__( | ||
ShowTextWithGlyphPositioning(), s | ||
) | ||
self._old_fonts: typing.List[Font] = old_fonts | ||
self._new_fonts: typing.List[Font] = new_fonts | ||
self._s: bytearray = s | ||
|
||
def _to_hex(self, i: int) -> str: | ||
s: str = hex(int(i))[2:] | ||
while len(s) < 2: | ||
s = "0" + s | ||
return s | ||
|
||
def invoke( | ||
self, | ||
canvas_stream_processor: "CanvasStreamProcessor", # type: ignore [name-defined] | ||
operands: typing.List[AnyPDFType] = [], | ||
event_listeners: typing.List["EventListener"] = [], # type: ignore [name-defined] | ||
) -> None: | ||
""" | ||
Invoke the TJ operator | ||
""" | ||
|
||
assert isinstance(operands[0], List), "Operand 0 of TJ must be a List" | ||
canvas = canvas_stream_processor.get_canvas() | ||
|
||
# handle Font being a Name (optimization) | ||
assert canvas.graphics_state.font is not None | ||
font_name: typing.Optional[Name] = None | ||
if isinstance(canvas.graphics_state.font, Name): | ||
# fmt: off | ||
font_name = canvas.graphics_state.font | ||
canvas.graphics_state.font = canvas_stream_processor.get_resource("Font", canvas.graphics_state.font) | ||
# fmt: on | ||
|
||
# we're only interested in the old_font | ||
if canvas.graphics_state.font not in self._old_fonts: | ||
return super(SubSetShowTextWithGlyphPositioning, self).invoke( | ||
canvas_stream_processor, operands, event_listeners | ||
) | ||
|
||
old_font: Font = canvas.graphics_state.font | ||
new_font: Font = self._new_fonts[self._old_fonts.index(old_font)] | ||
|
||
# modify the operands | ||
operands_out: typing.List[AnyPDFType] = [] | ||
for i in range(0, len(operands[0])): | ||
obj = operands[0][i] | ||
|
||
# adjust | ||
if isinstance(obj, Decimal): | ||
operands_out.append(obj) | ||
continue | ||
|
||
# display string | ||
if isinstance(obj, String): | ||
old_char: str = old_font.character_identifier_to_unicode( | ||
int(str(obj), 16) | ||
) | ||
new_code: str = self._to_hex( | ||
new_font.unicode_to_character_identifier(old_char) | ||
) | ||
operands_out.append(HexadecimalString(new_code)) | ||
|
||
# delegate | ||
return super(SubSetShowTextWithGlyphPositioning, self).invoke( | ||
canvas_stream_processor, [operands_out], event_listeners | ||
) |
Oops, something went wrong.