├── CHANGELOG.md ├── CONTRIBUTING.md ├── .github └── FUNDING.yml ├── .gitignore ├── examples ├── images │ ├── leaf.png │ └── qr-code.png └── fonts │ ├── Lato-Bold.ttf │ ├── Lato-Thin.ttf │ ├── Lato-Black.ttf │ ├── Lato-Italic.ttf │ ├── Lato-Light.ttf │ ├── Lato-Regular.ttf │ ├── Lato-BlackItalic.ttf │ ├── Lato-BoldItalic.ttf │ ├── Lato-LightItalic.ttf │ └── Lato-ThinItalic.ttf ├── src ├── Component │ ├── TableDataCellComponent.php │ ├── Size.php │ ├── TableRowComponent.php │ ├── TableFootComponent.php │ ├── TableHeadComponent.php │ ├── TableBodyComponent.php │ ├── TableHeadCellComponent.php │ ├── Width.php │ ├── Height.php │ ├── LineWidth.php │ ├── Base │ │ └── BaseComponent.php │ ├── RectangleComponent.php │ ├── TableComponent.php │ └── Position.php ├── Graphics │ ├── Path.php │ ├── Graphics.php │ ├── OverprintMode.php │ ├── PatternType.php │ ├── PaintType.php │ ├── ColourComponents.php │ ├── DeviceColourSpace.php │ ├── Shading.php │ ├── CIEColourSpace.php │ ├── XObject.php │ ├── ClippingPath.php │ ├── SpecialColourSpace.php │ ├── LineCapStyle.php │ ├── LineJoinStyle.php │ ├── TilingType.php │ ├── ShadingType.php │ ├── RenderingIntent.php │ └── Colour.php ├── Text │ ├── Text.php │ ├── TextAlign.php │ ├── TextObject.php │ ├── RenderingMode.php │ └── Encoding.php ├── Util │ └── Point.php ├── Type │ ├── Base │ │ ├── NameType.php │ │ ├── NullType.php │ │ ├── RealType.php │ │ ├── StringType.php │ │ ├── BooleanType.php │ │ ├── CommentType.php │ │ ├── FunctionType.php │ │ ├── IntegerType.php │ │ ├── StreamType.php │ │ ├── DictionaryType.php │ │ ├── ArrayType.php │ │ └── DateType.php │ ├── ByteStringType.php │ ├── ASCIIStringType.php │ ├── ContentStreamType.php │ ├── PDFDocEncodedStringType.php │ ├── TextStreamType.php │ ├── CoonsPatchMeshShadingDictionaryType.php │ ├── RenditionBestEffortDictionaryType.php │ ├── FreeFormTriangleMeshShadingDictionaryType.php │ ├── TextStringType.php │ ├── TensorProductPatchMeshShadingDictionaryType.php │ ├── PostScriptCalculatorFunctionType.php │ ├── RenditionMustHonourDictionaryType.php │ ├── LimitsArrayType.php │ ├── LiteralStringType.php │ ├── ExDataDictionaryType.php │ ├── FontDictionaryType.php │ ├── IntegerKeyArrayType.php │ ├── SelectorRenditionDictionaryType.php │ ├── NumberType.php │ ├── LiteralStringKeyArrayType.php │ ├── ExtensionsDictionaryType.php │ ├── PageTreeDictionaryType.php │ ├── PostScriptXObjectStreamType.php │ ├── CalRGBColourSpaceDictionaryType.php │ ├── DeveloperExtensionDictionaryType.php │ ├── MediaRenditionDictionaryType.php │ ├── NumberTreeDictionaryType.php │ ├── NameTreeDictionaryType.php │ ├── IntegersArrayType.php │ ├── FileSpecificationStringType.php │ ├── PageLabelsNumberTreeDictionaryType.php │ ├── TreeDictionaryType.php │ ├── HexadecimalStringType.php │ ├── DeviceNProcessDictionaryType.php │ ├── CollectionItemDictionaryType.php │ ├── PatternDictionaryType.php │ ├── EmbeddedFileStreamType.php │ ├── ThreadDictionaryType.php │ ├── LatticeFormTriangleMeshShadingDictionaryType.php │ ├── OutlineDictionaryType.php │ ├── MediaClipDictionaryType.php │ ├── MinimumScreenSizeDictionaryType.php │ ├── BooleansArrayType.php │ ├── MinimumBitDepthDictionaryType.php │ ├── DeviceNMixingHintsDictionaryType.php │ ├── DeviceNColourSpaceAttributesDictionaryType.php │ ├── ExponentialInterpolationFunctionType.php │ ├── PageLabelDictionaryType.php │ ├── NumbersArrayType.php │ ├── ByteStringsArrayType.php │ ├── CollectionSubItemDictionaryType.php │ ├── RenditionDictionaryType.php │ ├── MacOSFileInformationDictionaryType.php │ ├── ShadingPatternDictionaryType.php │ └── TextAnnotationDictionaryType.php ├── Document │ ├── BorderEffect.php │ ├── RelationshipType.php │ ├── AnnotationState │ │ ├── AnnotationState.php │ │ ├── AnnotationStateNone.php │ │ ├── AnnotationStateMarked.php │ │ ├── AnnotationStateAccepted.php │ │ ├── AnnotationStateCancelled.php │ │ ├── AnnotationStateCompleted.php │ │ ├── AnnotationStateRejected.php │ │ └── AnnotationStateUnmarked.php │ ├── Direction.php │ ├── PrintScaling.php │ ├── AnnotationJustification.php │ ├── TabOrder.php │ ├── BorderStyle.php │ ├── Duplex.php │ ├── Trapped.php │ ├── AnnotationHighlightMode.php │ ├── PageBoundaries.php │ ├── ProcedureSet.php │ ├── NumberingStyle.php │ ├── AnnotationIT.php │ ├── AnnotationFlag.php │ ├── PageMode.php │ ├── PageLayout.php │ └── LineEndingStyle.php ├── Validator │ ├── Base │ │ └── Validator.php │ ├── BooleanValidator.php │ ├── StringValidator.php │ ├── ArrayValidator.php │ ├── ByteStringValidator.php │ ├── DateValidator.php │ ├── BitsPerFlagValidator.php │ ├── DirectionValidator.php │ ├── BitsPerSampleValidator.php │ ├── TabOrderValidator.php │ ├── BooleansArrayValidator.php │ ├── BorderEffectValidator.php │ ├── NumberValidator.php │ ├── RelationshipTypeValidator.php │ ├── BitsPerComponentValidator.php │ ├── EncodingValidator.php │ ├── IntegersArrayValidator.php │ ├── TrappedValidator.php │ ├── FontWeightValidator.php │ ├── PrintScalingValidator.php │ ├── BitsPerCoordinateValidator.php │ ├── ByteStringsArrayValidator.php │ ├── DuplexValidator.php │ ├── NumbersArrayValidator.php │ ├── MediaClipValidator.php │ ├── PatternTypeValidator.php │ ├── IntegerValidator.php │ ├── PaintTypeValidator.php │ ├── VersionValidator.php │ ├── OverprintModeValidator.php │ ├── RealValidator.php │ ├── BorderStyleValidator.php │ ├── DeviceColourSpaceValidator.php │ ├── LineCapStyleValidator.php │ ├── LineJoinStyleValidator.php │ ├── TilingTypeValidator.php │ ├── NumberingStyleValidator.php │ ├── RenderingIntentValidator.php │ ├── PageModeValidator.php │ ├── AnnotationJustificationValidator.php │ ├── PageBoundariesValidator.php │ ├── RenditionTypeValidator.php │ ├── FunctionTypeValidator.php │ ├── AnnotationHighlightModeValidator.php │ ├── AnnotationITValidator.php │ ├── ColourComponentsValidator.php │ ├── FontStretchValidator.php │ ├── PageLayoutValidator.php │ ├── PredictorValidator.php │ ├── ShadingTypeValidator.php │ ├── LineEndingStyleValidator.php │ ├── FontDescriptorFlagValidator.php │ ├── RenderingModeValidator.php │ ├── AnnotationFlagValidator.php │ └── AnnotationTypeValidator.php ├── Object │ ├── NullObject.php │ ├── IntegerObject.php │ ├── RealObject.php │ ├── CommentObject.php │ ├── NameObject.php │ ├── BaseObject.php │ └── StringObject.php ├── Multimedia │ ├── MediaClip.php │ └── Rendition.php ├── Filter │ ├── ASCII85EncodeFilter.php │ ├── ASCIIHexEncodeFilter.php │ ├── FlateEncodeFilter.php │ ├── LZWDecodeFilter.php │ ├── LZWEncodeFilter.php │ ├── ASCII85DecodeFilter.php │ ├── ASCIIHexDecodeFilter.php │ ├── FlateDecodeFilter.php │ ├── Base │ │ └── Filter.php │ ├── Params │ │ └── LZWDecodeParams.php │ ├── Predictor.php │ ├── FlateFilter.php │ ├── FilterType.php │ └── ASCIIHexFilter.php ├── Functions │ └── FunctionType.php ├── Helpers │ └── MetricHelper.php ├── Font │ ├── FontDescriptorFlag.php │ └── FontStretch.php ├── File │ ├── CrossReferenceTable.php │ ├── CrossReference │ │ ├── CrossReferenceSection.php │ │ └── CrossReferenceSubSection.php │ └── FileHeader.php ├── Repository │ └── Repository.php └── Factory │ └── Factory.php ├── composer.json └── LICENSE.md /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | buy_me_a_coffee: mikaelcarlavan 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | *.DS_Store 3 | composer.lock 4 | *.pdf 5 | .idea 6 | /public 7 | /doc 8 | -------------------------------------------------------------------------------- /examples/images/leaf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikaelcarlavan/papier/HEAD/examples/images/leaf.png -------------------------------------------------------------------------------- /examples/fonts/Lato-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikaelcarlavan/papier/HEAD/examples/fonts/Lato-Bold.ttf -------------------------------------------------------------------------------- /examples/fonts/Lato-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikaelcarlavan/papier/HEAD/examples/fonts/Lato-Thin.ttf -------------------------------------------------------------------------------- /examples/images/qr-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikaelcarlavan/papier/HEAD/examples/images/qr-code.png -------------------------------------------------------------------------------- /examples/fonts/Lato-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikaelcarlavan/papier/HEAD/examples/fonts/Lato-Black.ttf -------------------------------------------------------------------------------- /examples/fonts/Lato-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikaelcarlavan/papier/HEAD/examples/fonts/Lato-Italic.ttf -------------------------------------------------------------------------------- /examples/fonts/Lato-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikaelcarlavan/papier/HEAD/examples/fonts/Lato-Light.ttf -------------------------------------------------------------------------------- /examples/fonts/Lato-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikaelcarlavan/papier/HEAD/examples/fonts/Lato-Regular.ttf -------------------------------------------------------------------------------- /examples/fonts/Lato-BlackItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikaelcarlavan/papier/HEAD/examples/fonts/Lato-BlackItalic.ttf -------------------------------------------------------------------------------- /examples/fonts/Lato-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikaelcarlavan/papier/HEAD/examples/fonts/Lato-BoldItalic.ttf -------------------------------------------------------------------------------- /examples/fonts/Lato-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikaelcarlavan/papier/HEAD/examples/fonts/Lato-LightItalic.ttf -------------------------------------------------------------------------------- /examples/fonts/Lato-ThinItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikaelcarlavan/papier/HEAD/examples/fonts/Lato-ThinItalic.ttf -------------------------------------------------------------------------------- /src/Component/TableDataCellComponent.php: -------------------------------------------------------------------------------- 1 | value = null; 16 | } 17 | } -------------------------------------------------------------------------------- /src/Document/AnnotationState/AnnotationState.php: -------------------------------------------------------------------------------- 1 | setEntry('ShadingType', ShadingType::COONS_PATCH_MESH); 17 | return parent::format(); 18 | } 19 | } -------------------------------------------------------------------------------- /src/Graphics/DeviceColourSpace.php: -------------------------------------------------------------------------------- 1 | setEntry('C', $C); 18 | return $this; 19 | } 20 | } -------------------------------------------------------------------------------- /src/Type/FreeFormTriangleMeshShadingDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('ShadingType', ShadingType::FREE_FORM_TRIANGLE_MESH); 18 | return parent::format(); 19 | } 20 | } -------------------------------------------------------------------------------- /src/Type/TextStringType.php: -------------------------------------------------------------------------------- 1 | setEntry('ShadingType', ShadingType::TENSOR_PRODUCT_PATCH_MESH); 17 | 18 | return parent::format(); 19 | } 20 | } -------------------------------------------------------------------------------- /src/Text/TextObject.php: -------------------------------------------------------------------------------- 1 | addToContent($state); 16 | } 17 | 18 | /** 19 | * End a text object. 20 | * 21 | * @return mixed 22 | */ 23 | public function endText() 24 | { 25 | $state = 'ET'; 26 | return $this->addToContent($state); 27 | } 28 | } -------------------------------------------------------------------------------- /src/Filter/ASCII85EncodeFilter.php: -------------------------------------------------------------------------------- 1 | setFunctionType(FuncType::POSTSCRIPT_CALCULATOR); 20 | 21 | return parent::format(); 22 | } 23 | } -------------------------------------------------------------------------------- /src/Document/BorderStyle.php: -------------------------------------------------------------------------------- 1 | setEntry('C', $C); 20 | return $this; 21 | } 22 | } -------------------------------------------------------------------------------- /src/Document/Trapped.php: -------------------------------------------------------------------------------- 1 | getObjects(); 19 | $value = ''; 20 | foreach ($objects as $object) { 21 | /** @var BaseObject $object */ 22 | $value .= ' '.$object->format(); 23 | } 24 | 25 | return '[' .trim($value). ']'; 26 | } 27 | } -------------------------------------------------------------------------------- /src/Type/LiteralStringType.php: -------------------------------------------------------------------------------- 1 | getValue(); 20 | 21 | $trans = array('(' => '\(', ')' => '\)', '\\' => '\\\\'); 22 | $value = strtr($value, $trans); 23 | 24 | return '(' .$value. ')'; 25 | } 26 | } -------------------------------------------------------------------------------- /src/Graphics/Shading.php: -------------------------------------------------------------------------------- 1 | format()); 20 | return $this->addToContent($state); 21 | } 22 | } -------------------------------------------------------------------------------- /src/Graphics/CIEColourSpace.php: -------------------------------------------------------------------------------- 1 | format()); 20 | return $this->addToContent($state); 21 | } 22 | } -------------------------------------------------------------------------------- /src/Type/ExDataDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('Type', $type); 19 | 20 | $type = Factory::create('Papier\Type\Base\NameType', 'Markup3D'); 21 | $this->setEntry('Subtype', $type); 22 | 23 | return parent::format(); 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /src/Validator/ArrayValidator.php: -------------------------------------------------------------------------------- 1 | 0) { 20 | $isValid = $isValid && (count($value) == $size); 21 | } 22 | 23 | return $isValid; 24 | } 25 | } -------------------------------------------------------------------------------- /src/Validator/ByteStringValidator.php: -------------------------------------------------------------------------------- 1 | addToContent($state); 16 | } 17 | 18 | /** 19 | * Modify the clipping path using the even-odd window rule. 20 | * 21 | * @return mixed 22 | */ 23 | public function evenOddModify() 24 | { 25 | $state = 'W*'; 26 | return $this->addToContent($state); 27 | } 28 | } -------------------------------------------------------------------------------- /src/Functions/FunctionType.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | const BITS_PER_FLAG = array( 15 | 2, 4, 8 16 | ); 17 | 18 | 19 | /** 20 | * Test if given parameter is a valid bits per flag. 21 | * 22 | * @param int $value 23 | * @return bool 24 | */ 25 | public static function isValid($value): bool 26 | { 27 | return IntegerValidator::isValid($value) && in_array($value, self::BITS_PER_FLAG); 28 | } 29 | } -------------------------------------------------------------------------------- /src/Validator/DirectionValidator.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | const DIRECTIONS = array( 15 | Direction::LEFT_TO_RIGHT, 16 | Direction::RIGHT_TO_LEFT, 17 | ); 18 | 19 | 20 | /** 21 | * Test if given parameter is a valid direction. 22 | * 23 | * @param string $value 24 | * @return bool 25 | */ 26 | public static function isValid($value): bool 27 | { 28 | return parent::isValid($value) && in_array($value, self::DIRECTIONS); 29 | } 30 | } -------------------------------------------------------------------------------- /src/Document/PageBoundaries.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | const BITS_PER_SAMPLE = array( 15 | 1, 2, 4, 8, 12, 16, 24, 32 16 | ); 17 | 18 | 19 | /** 20 | * Test if given parameter is a valid bits per sample. 21 | * 22 | * @param int $value 23 | * @return bool 24 | */ 25 | public static function isValid($value): bool 26 | { 27 | return IntegerValidator::isValid($value) && in_array($value, self::BITS_PER_SAMPLE); 28 | } 29 | } -------------------------------------------------------------------------------- /src/Validator/TabOrderValidator.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | const TAB_ORDERS = array( 15 | TabOrder::ROW, 16 | TabOrder::COLUMN, 17 | TabOrder::STRUCTURE, 18 | ); 19 | 20 | 21 | /** 22 | * Test if given parameter is a valid tab order. 23 | * 24 | * @param mixed $value 25 | * @return bool 26 | */ 27 | public static function isValid($value): bool 28 | { 29 | return parent::isValid($value) && in_array($value, self::TAB_ORDERS); 30 | } 31 | } -------------------------------------------------------------------------------- /src/Validator/BooleansArrayValidator.php: -------------------------------------------------------------------------------- 1 | $value */ 20 | foreach ($value as $number) { 21 | $isValid = $isValid && BooleanValidator::isValid($number); 22 | } 23 | } 24 | 25 | return $isValid; 26 | } 27 | } -------------------------------------------------------------------------------- /src/Validator/BorderEffectValidator.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const EFFECTS = array( 17 | BorderEffect::NO_EFFECT, 18 | BorderEffect::CLOUDY, 19 | ); 20 | 21 | 22 | /** 23 | * Test if given parameter is a valid effect 24 | * 25 | * @param string $value 26 | * @return bool 27 | */ 28 | public static function isValid($value): bool 29 | { 30 | return StringValidator::isValid($value) && in_array($value, self::EFFECTS); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Validator/NumberValidator.php: -------------------------------------------------------------------------------- 1 | = $min); 21 | } 22 | if (is_numeric($max) && $isValid) { 23 | $isValid = ($value <= $max); 24 | } 25 | return $isValid; 26 | } 27 | } -------------------------------------------------------------------------------- /src/Validator/RelationshipTypeValidator.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const TYPES = array( 17 | RelationshipType::REPLY, 18 | RelationshipType::GROUP, 19 | ); 20 | 21 | 22 | /** 23 | * Test if given parameter is a valid type 24 | * 25 | * @param string $value 26 | * @return bool 27 | */ 28 | public static function isValid($value): bool 29 | { 30 | return StringValidator::isValid($value) && in_array($value, self::TYPES); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Validator/BitsPerComponentValidator.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | const BITS_PER_COMPONENT = array( 15 | 1, 2, 4, 8, 12, 16 16 | ); 17 | 18 | 19 | /** 20 | * Test if given parameter is a valid bits per component. 21 | * 22 | * @param int $value 23 | * @return bool 24 | */ 25 | public static function isValid($value): bool 26 | { 27 | return IntegerValidator::isValid($value) && in_array($value, self::BITS_PER_COMPONENT); 28 | } 29 | } -------------------------------------------------------------------------------- /src/Validator/EncodingValidator.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | const ENCODINGS = array( 15 | Encoding::MAC_ROMAN, 16 | Encoding::MAC_EXPERT, 17 | Encoding::WIN_ANSI, 18 | ); 19 | 20 | 21 | /** 22 | * Test if given parameter is a valid device colour space. 23 | * 24 | * @param string $value 25 | * @return bool 26 | */ 27 | public static function isValid($value): bool 28 | { 29 | return parent::isValid($value) && in_array($value, self::ENCODINGS); 30 | } 31 | } -------------------------------------------------------------------------------- /src/Validator/IntegersArrayValidator.php: -------------------------------------------------------------------------------- 1 | $value */ 20 | foreach ($value as $number) { 21 | $isValid = $isValid && IntegerValidator::isValid($number); 22 | } 23 | } 24 | 25 | return $isValid; 26 | } 27 | } -------------------------------------------------------------------------------- /src/Validator/TrappedValidator.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | const TRAPPED_VALUES = array( 15 | Trapped::TRUE, 16 | Trapped::FALSE, 17 | Trapped::UNKNOWN, 18 | ); 19 | 20 | 21 | /** 22 | * Test if given parameter is a valid trapped value. 23 | * 24 | * @param string $value 25 | * @return bool 26 | */ 27 | public static function isValid($value): bool 28 | { 29 | return parent::isValid($value) && in_array($value, self::TRAPPED_VALUES); 30 | } 31 | } -------------------------------------------------------------------------------- /src/Validator/FontWeightValidator.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | const FONT_WEIGHTS = array( 16 | 100, 17 | 200, 18 | 300, 19 | 400, 20 | 500, 21 | 600, 22 | 700, 23 | 800, 24 | 900 25 | ); 26 | 27 | 28 | /** 29 | * Test if given parameter is a valid bits per component. 30 | * 31 | * @param int $value 32 | * @return bool 33 | */ 34 | public static function isValid($value): bool 35 | { 36 | return IntegerValidator::isValid($value) && in_array($value, self::FONT_WEIGHTS); 37 | } 38 | } -------------------------------------------------------------------------------- /src/Validator/PrintScalingValidator.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | const PRINT_SCALING_TYPES = array( 15 | PrintScaling::NONE, 16 | PrintScaling::APP_DEFAULT, 17 | ); 18 | 19 | 20 | /** 21 | * Test if given parameter is a valid page mode. 22 | * 23 | * @param string $value 24 | * @return bool 25 | */ 26 | public static function isValid($value): bool 27 | { 28 | return parent::isValid($value) && in_array($value, self::PRINT_SCALING_TYPES); 29 | } 30 | } -------------------------------------------------------------------------------- /src/Validator/BitsPerCoordinateValidator.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | const BITS_PER_COORDINATEE = array( 15 | 1, 2, 4, 8, 12, 16, 24, 32 16 | ); 17 | 18 | 19 | /** 20 | * Test if given parameter is a valid bits per coordinate. 21 | * 22 | * @param int $value 23 | * @return bool 24 | */ 25 | public static function isValid($value): bool 26 | { 27 | return IntegerValidator::isValid($value) && in_array($value, self::BITS_PER_COORDINATEE); 28 | } 29 | } -------------------------------------------------------------------------------- /src/Validator/ByteStringsArrayValidator.php: -------------------------------------------------------------------------------- 1 | $value */ 20 | foreach ($value as $string) { 21 | $isValid = $isValid && ByteStringValidator::isValid($string); 22 | } 23 | } 24 | 25 | return $isValid; 26 | } 27 | } -------------------------------------------------------------------------------- /src/Validator/DuplexValidator.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | const DUPLEX_TYPES = array( 15 | Duplex::SIMPLEX, 16 | Duplex::DUPLEX_FLIP_SHORT_EDGE, 17 | Duplex::DUPLEX_FLIP_LONG_EDGE 18 | ); 19 | 20 | 21 | /** 22 | * Test if given parameter is a valid page mode. 23 | * 24 | * @param string $value 25 | * @return bool 26 | */ 27 | public static function isValid($value): bool 28 | { 29 | return parent::isValid($value) && in_array($value, self::DUPLEX_TYPES); 30 | } 31 | } -------------------------------------------------------------------------------- /src/Validator/NumbersArrayValidator.php: -------------------------------------------------------------------------------- 1 | $value */ 20 | foreach ($value as $number) { 21 | $isValid = $isValid && NumberValidator::isValid($number); 22 | } 23 | } 24 | 25 | return $isValid; 26 | } 27 | } -------------------------------------------------------------------------------- /src/Type/FontDictionaryType.php: -------------------------------------------------------------------------------- 1 | getEntryValue('Name'); 19 | return $value; 20 | } 21 | 22 | /** 23 | * Set name. 24 | * 25 | * @param string $name 26 | * @return FontDictionaryType 27 | */ 28 | public function setName(string $name): FontDictionaryType 29 | { 30 | $value = Factory::create('Papier\Type\Base\NameType', $name); 31 | $this->setEntry('Name', $value); 32 | return $this; 33 | } 34 | } -------------------------------------------------------------------------------- /src/Validator/MediaClipValidator.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const MEDIA_CLIP_VALUES = array( 17 | MediaClip::MEDIA_CLIP_DATA, 18 | MediaClip::MEDIA_CLIP_SECTION, 19 | ); 20 | 21 | 22 | /** 23 | * Test if given parameter is a valid media clip 24 | * 25 | * @param string $value 26 | * @return bool 27 | */ 28 | public static function isValid($value): bool 29 | { 30 | return StringValidator::isValid($value) && in_array($value, self::MEDIA_CLIP_VALUES); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Document/ProcedureSet.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const PATTERN_TYPES = array( 17 | PatternType::TILING_PATTERN, 18 | PatternType::SHADING_PATTERN, 19 | ); 20 | 21 | 22 | /** 23 | * Test if given parameter is a valid pattern type. 24 | * 25 | * @param int $value 26 | * @return bool 27 | */ 28 | public static function isValid($value): bool 29 | { 30 | return IntegerValidator::isValid($value) && in_array($value, self::PATTERN_TYPES); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Validator/IntegerValidator.php: -------------------------------------------------------------------------------- 1 | = $min); 21 | } 22 | if (is_int($max) && $isValid) { 23 | $isValid = ($value <= $max); 24 | } 25 | return $isValid; 26 | } 27 | } -------------------------------------------------------------------------------- /src/Validator/PaintTypeValidator.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const PAINT_TYPES = array( 17 | PaintType::COLOURED_TILING_PATTERN, 18 | PaintType::UNCOLOURED_TILING_PATTERN, 19 | ); 20 | 21 | 22 | /** 23 | * Test if given parameter is a valid paint type. 24 | * 25 | * @param int $value 26 | * @return bool 27 | */ 28 | public static function isValid($value): bool 29 | { 30 | return IntegerValidator::isValid($value) && in_array($value, self::PAINT_TYPES); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Validator/VersionValidator.php: -------------------------------------------------------------------------------- 1 | getObjects(); 22 | 23 | $value = ''; 24 | foreach ($objects as $key => $object) { 25 | /** @var IntegerType $object */ 26 | $name = Factory::create('Papier\Type\Base\IntegerType', $key); 27 | $value .= $name->format() .' '. $object->write(); 28 | } 29 | 30 | return '[' .$value. ']'; 31 | } 32 | } -------------------------------------------------------------------------------- /src/Validator/OverprintModeValidator.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const OVERPRINT_MODES = array( 17 | OverprintMode::NONZERO_MODE, 18 | OverprintMode::ZERO_MODE, 19 | ); 20 | 21 | 22 | /** 23 | * Test if given parameter is a valid overprint mode. 24 | * 25 | * @param int $value 26 | * @return bool 27 | */ 28 | public static function isValid($value): bool 29 | { 30 | return IntegerValidator::isValid($value) && in_array($value, self::OVERPRINT_MODES); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Validator/RealValidator.php: -------------------------------------------------------------------------------- 1 | = $min); 21 | } 22 | if (is_float($max) && $isValid) { 23 | $isValid = ($value <= $max); 24 | } 25 | return $isValid; 26 | } 27 | } -------------------------------------------------------------------------------- /src/Filter/Base/Filter.php: -------------------------------------------------------------------------------- 1 | $r 15 | * @return SelectorRenditionDictionaryType 16 | */ 17 | public function setR(array $r): SelectorRenditionDictionaryType 18 | { 19 | if (!ArrayValidator::isValid($r)) { 20 | throw new InvalidArgumentException("R is incorrect. See ".__CLASS__." class's documentation for possible values."); 21 | } 22 | 23 | $value = Factory::create('Papier\Type\Base\ArrayType', $r); 24 | 25 | $this->setEntry('R', $value); 26 | return $this; 27 | } 28 | } -------------------------------------------------------------------------------- /src/Validator/BorderStyleValidator.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const STYLES = array( 17 | BorderStyle::SOLID, 18 | BorderStyle::DASHED, 19 | BorderStyle::BEVELED, 20 | BorderStyle::INSET, 21 | BorderStyle::UNDERLINE, 22 | ); 23 | 24 | 25 | /** 26 | * Test if given parameter is a valid style 27 | * 28 | * @param string $value 29 | * @return bool 30 | */ 31 | public static function isValid($value): bool 32 | { 33 | return StringValidator::isValid($value) && in_array($value, self::STYLES); 34 | } 35 | } -------------------------------------------------------------------------------- /src/Validator/DeviceColourSpaceValidator.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | const DEVICE_COLOUR_SPACES = array( 15 | DeviceColourSpace::GRAY, 16 | DeviceColourSpace::RGB, 17 | DeviceColourSpace::CMYK, 18 | ); 19 | 20 | 21 | /** 22 | * Test if given parameter is a valid device colour space. 23 | * 24 | * @param string $value 25 | * @return bool 26 | */ 27 | public static function isValid($value): bool 28 | { 29 | return parent::isValid($value) && in_array($value, self::DEVICE_COLOUR_SPACES); 30 | } 31 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "papier/papier", 3 | "description": "Low-level PHP library for generating PDF files", 4 | "type": "library", 5 | "homepage": "https://papier.io", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Mikael Carlavan", 10 | "email": "mikael@camina.dev", 11 | "homepage": "https://camina.dev", 12 | "role": "Developer" 13 | } 14 | ], 15 | "require": { 16 | "php": ">=8.0", 17 | "ext-fileinfo": "*", 18 | "ext-iconv": "*" 19 | }, 20 | "require-dev": { 21 | "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35", 22 | "phpstan/phpstan": "^2.0" 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "Papier\\": "src/" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Type/NumberType.php: -------------------------------------------------------------------------------- 1 | getObjects(); 21 | 22 | $value = ''; 23 | foreach ($objects as $key => $object) { 24 | /** @var LiteralStringType $object */ 25 | /** @var LiteralStringType $name */ 26 | $name = Factory::create('Papier\Type\LiteralStringType', $key); 27 | $value .= $name->format() .' '. $object->write(); 28 | } 29 | 30 | return '[' .$value. ']'; 31 | } 32 | } -------------------------------------------------------------------------------- /src/Validator/LineCapStyleValidator.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const LINE_CAP_STYLES = array( 17 | LineCapStyle::BUTT_CAP, 18 | LineCapStyle::ROUND_CAP, 19 | LineCapStyle::PROJECTING_SQUARE_CAP, 20 | ); 21 | 22 | 23 | /** 24 | * Test if given parameter is a valid line cap style. 25 | * 26 | * @param int $value 27 | * @return bool 28 | */ 29 | public static function isValid($value): bool 30 | { 31 | return IntegerValidator::isValid($value) && in_array($value, self::LINE_CAP_STYLES); 32 | } 33 | } -------------------------------------------------------------------------------- /src/Validator/LineJoinStyleValidator.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const LINE_JOIN_STYLES = array( 17 | LineJoinStyle::MITER_JOIN, 18 | LineJoinStyle::ROUND_JOIN, 19 | LineJoinStyle::BEVEL_JOIN, 20 | ); 21 | 22 | 23 | /** 24 | * Test if given parameter is a valid line join style. 25 | * 26 | * @param int $value 27 | * @return bool 28 | */ 29 | public static function isValid($value): bool 30 | { 31 | return IntegerValidator::isValid($value) && in_array($value, self::LINE_JOIN_STYLES); 32 | } 33 | } -------------------------------------------------------------------------------- /src/Validator/TilingTypeValidator.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const TILING_TYPES = array( 17 | TilingType::CONSTANT_SPACING, 18 | TilingType::NO_DISTORTION, 19 | TilingType::CONSTANT_SPACING_AND_FASTER_TILING, 20 | ); 21 | 22 | 23 | /** 24 | * Test if given parameter is a valid paint type. 25 | * 26 | * @param int $value 27 | * @return bool 28 | */ 29 | public static function isValid($value): bool 30 | { 31 | return IntegerValidator::isValid($value) && in_array($value, self::TILING_TYPES); 32 | } 33 | } -------------------------------------------------------------------------------- /src/Document/NumberingStyle.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | const NUMBERING_STYLES = array( 16 | NumberingStyle::DECIMAL_ARABIC, 17 | NumberingStyle::UPPERCASE_LETTERS, 18 | NumberingStyle::LOWERCASE_LETTERS, 19 | NumberingStyle::UPPERCASE_ROMAN, 20 | NumberingStyle::LOWERCASE_ROMAN 21 | ); 22 | 23 | 24 | /** 25 | * Test if given parameter is a valid numbering style. 26 | * 27 | * @param string $value 28 | * @return bool 29 | */ 30 | public static function isValid($value): bool 31 | { 32 | return StringValidator::isValid($value) && in_array($value, self::NUMBERING_STYLES); 33 | } 34 | } -------------------------------------------------------------------------------- /src/Validator/RenderingIntentValidator.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | const RENDERING_INTENTS = array( 15 | RenderingIntent::ABSOLUTE_COLORIMETRIC, 16 | RenderingIntent::RELATIVE_COLORIMETRIC, 17 | RenderingIntent::SATURATION, 18 | RenderingIntent::PERCEPTUAL, 19 | ); 20 | 21 | 22 | /** 23 | * Test if given parameter is a valid rendering intent. 24 | * 25 | * @param string $value 26 | * @return bool 27 | */ 28 | public static function isValid($value): bool 29 | { 30 | return parent::isValid($value) && in_array($value, self::RENDERING_INTENTS); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Validator/PageModeValidator.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | const PAGE_MODES = array( 15 | PageMode::USE_NONE_MODE, 16 | PageMode::USE_OUTLINES_MODE, 17 | PageMode::USE_THUMBS_MODE, 18 | PageMode::FULL_SCREEN_MODE, 19 | PageMode::USE_OC_MODE, 20 | PageMode::USE_ATTACHMENTS_MODE, 21 | ); 22 | 23 | 24 | /** 25 | * Test if given parameter is a valid page mode. 26 | * 27 | * @param string $value 28 | * @return bool 29 | */ 30 | public static function isValid($value): bool 31 | { 32 | return parent::isValid($value) && in_array($value, self::PAGE_MODES); 33 | } 34 | } -------------------------------------------------------------------------------- /src/Filter/Params/LZWDecodeParams.php: -------------------------------------------------------------------------------- 1 | setEntry('Columns', $value); 27 | return $this; 28 | } 29 | } -------------------------------------------------------------------------------- /src/Validator/AnnotationJustificationValidator.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const ANNOTATION_JUSTIFICATIONS = array( 17 | AnnotationJustification::LEFT_JUSTIFIED, 18 | AnnotationJustification::CENTERED, 19 | AnnotationJustification::RIGHT_JUSTIFIED, 20 | ); 21 | 22 | 23 | /** 24 | * Test if given parameter is a valid type 25 | * 26 | * @param int $value 27 | * @return bool 28 | */ 29 | public static function isValid($value): bool 30 | { 31 | return IntegerValidator::isValid($value) && in_array($value, self::ANNOTATION_JUSTIFICATIONS); 32 | } 33 | } -------------------------------------------------------------------------------- /src/Validator/PageBoundariesValidator.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | const PAGE_BOUNDARIES_TYPES = array( 15 | PageBoundaries::MEDIA_BOX, 16 | PageBoundaries::CROP_BOX, 17 | PageBoundaries::TRIM_BOX, 18 | PageBoundaries::BLEED_BOX, 19 | PageBoundaries::ART_BOX, 20 | ); 21 | 22 | 23 | /** 24 | * Test if given parameter is a valid page mode. 25 | * 26 | * @param mixed $value 27 | * @return bool 28 | */ 29 | public static function isValid($value): bool 30 | { 31 | return parent::isValid($value) && in_array($value, self::PAGE_BOUNDARIES_TYPES); 32 | } 33 | } -------------------------------------------------------------------------------- /src/Validator/RenditionTypeValidator.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | const RENDITION_TYPES = array( 18 | Rendition::MEDIA_RENDITION_TYPE, 19 | Rendition::SELECTOR_RENDITION_TYPE, 20 | ); 21 | 22 | 23 | /** 24 | * Test if given parameter is a valid rendition type. 25 | * 26 | * @param string $value 27 | * @return bool 28 | */ 29 | public static function isValid($value): bool 30 | { 31 | return StringValidator::isValid($value) && in_array($value, self::RENDITION_TYPES); 32 | } 33 | } -------------------------------------------------------------------------------- /src/Type/ExtensionsDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry($name, $extension); 27 | return $extension; 28 | } 29 | } -------------------------------------------------------------------------------- /src/Validator/FunctionTypeValidator.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const FUNCTION_TYPES = array( 17 | FunctionType::SAMPLED, 18 | FunctionType::EXPONENTIAL_INTERPOLATION, 19 | FunctionType::STITCHING, 20 | FunctionType::POSTSCRIPT_CALCULATOR, 21 | ); 22 | 23 | 24 | /** 25 | * Test if given parameter is a valid function type. 26 | * 27 | * @param int $value 28 | * @return bool 29 | */ 30 | public static function isValid($value): bool 31 | { 32 | return IntegerValidator::isValid($value) && in_array($value, self::FUNCTION_TYPES); 33 | } 34 | } -------------------------------------------------------------------------------- /src/Validator/AnnotationHighlightModeValidator.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const ANNOTATION_HIGHLIGHT_MODES = array( 17 | AnnotationHighlightMode::INVERT, 18 | AnnotationHighlightMode::OUTLINE, 19 | AnnotationHighlightMode::NONE, 20 | AnnotationHighlightMode::PUSH, 21 | ); 22 | 23 | /** 24 | * Test if given parameter is a valid annotation highlight mode. 25 | * 26 | * @param string $value 27 | * @return bool 28 | */ 29 | public static function isValid($value): bool 30 | { 31 | return StringValidator::isValid($value) && in_array($value, self::ANNOTATION_HIGHLIGHT_MODES); 32 | } 33 | } -------------------------------------------------------------------------------- /src/Validator/AnnotationITValidator.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const ANNOTATION_ITS = array( 17 | AnnotationIT::FREE_TEXT, 18 | AnnotationIT::FREE_TEXT_CALLOUT, 19 | AnnotationIT::FREE_TEXT_TYPE_WRITER, 20 | AnnotationIT::FREE_TEXT_TYPE_WRITER, 21 | AnnotationIT::FREE_TEXT_TYPE_WRITER, 22 | ); 23 | 24 | 25 | /** 26 | * Test if given parameter is a valid type 27 | * 28 | * @param string $value 29 | * @return bool 30 | */ 31 | public static function isValid($value): bool 32 | { 33 | return StringValidator::isValid($value) && in_array($value, self::ANNOTATION_ITS); 34 | } 35 | } -------------------------------------------------------------------------------- /src/Validator/ColourComponentsValidator.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | const COMPONENTS_VALUES = array( 18 | ColourComponents::ONE, 19 | ColourComponents::THREE, 20 | ColourComponents::FOUR, 21 | ); 22 | 23 | 24 | /** 25 | * Test if given parameter is a valid number of components. 26 | * 27 | * @param int $value 28 | * @return bool 29 | */ 30 | public static function isValid($value): bool 31 | { 32 | return IntegerValidator::isValid($value) && in_array($value, self::COMPONENTS_VALUES); 33 | } 34 | } -------------------------------------------------------------------------------- /src/Validator/FontStretchValidator.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | const FONT_STRETCHES = array( 16 | FontStretch::ULTRA_CONDENSED, 17 | FontStretch::EXTRA_CONDENSED, 18 | FontStretch::SEMI_CONDENSED, 19 | FontStretch::CONDENSED, 20 | FontStretch::NORMAL, 21 | FontStretch::SEMI_EXPANDED, 22 | FontStretch::EXPANDED, 23 | FontStretch::ULTRA_EXPANDED, 24 | ); 25 | 26 | 27 | /** 28 | * Test if given parameter is a valid device colour space. 29 | * 30 | * @param string $value 31 | * @return bool 32 | */ 33 | public static function isValid($value): bool 34 | { 35 | return parent::isValid($value) && in_array($value, self::FONT_STRETCHES); 36 | } 37 | } -------------------------------------------------------------------------------- /src/Document/AnnotationIT.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | const PAGE_LAYOUTS = array( 15 | PageLayout::SINGLE_PAGE_LAYOUT, 16 | PageLayout::ONE_COLUMN_LAYOUT, 17 | PageLayout::TWO_COLUMN_LEFT_LAYOUT, 18 | PageLayout::TWO_COLUMN_RIGHT_LAYOUT, 19 | PageLayout::TWO_PAGE_LEFT_LAYOUT, 20 | PageLayout::TWO_PAGE_RIGHT_LAYOUT, 21 | ); 22 | 23 | /** 24 | * Test if given parameter is a valid page layout. 25 | * 26 | * @param string $value 27 | * @return bool 28 | */ 29 | public static function isValid($value): bool 30 | { 31 | return parent::isValid($value) && in_array($value, self::PAGE_LAYOUTS); 32 | } 33 | } -------------------------------------------------------------------------------- /src/Helpers/MetricHelper.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const PREDICTORS = array( 17 | Predictor::NONE, 18 | Predictor::TIFF_2, 19 | Predictor::PNG_NONE, 20 | Predictor::PNG_SUB, 21 | Predictor::PNG_UP, 22 | Predictor::PNG_AVERAGE, 23 | Predictor::PNG_PAETH, 24 | Predictor::PNG_OPTIMUM 25 | ); 26 | 27 | 28 | /** 29 | * Test if given parameter is a valid predictor. 30 | * 31 | * @param int $value 32 | * @return bool 33 | */ 34 | public static function isValid($value): bool 35 | { 36 | return IntegerValidator::isValid($value) && in_array($value, self::PREDICTORS); 37 | } 38 | } -------------------------------------------------------------------------------- /src/Font/FontDescriptorFlag.php: -------------------------------------------------------------------------------- 1 | hasEntry('Node')) { 18 | $node = Factory::create('Papier\Type\PageTreeNodeDictionaryType', null, true); 19 | $this->setEntry('Node', $node); 20 | } 21 | 22 | /** @var PageTreeNodeDictionaryType $node */ 23 | $node = $this->getEntry('Node'); 24 | return $node; 25 | } 26 | 27 | /** 28 | * Format object's value. 29 | * 30 | * @return string 31 | */ 32 | public function format(): string 33 | { 34 | $node = $this->getNode(); 35 | return $node->format(); 36 | } 37 | } -------------------------------------------------------------------------------- /src/Type/PostScriptXObjectStreamType.php: -------------------------------------------------------------------------------- 1 | setEntry('Level1', $level1); 20 | return $this; 21 | } 22 | 23 | /** 24 | * Format object's content. 25 | * 26 | * @return string 27 | */ 28 | public function format(): string 29 | { 30 | $type = Factory::create('Papier\Type\Base\NameType', 'PS'); 31 | $this->setEntry('Subtype', $type); 32 | 33 | return parent::format(); 34 | } 35 | } -------------------------------------------------------------------------------- /src/Validator/ShadingTypeValidator.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const SHADING_TYPES = array( 17 | ShadingType::FUNCTION_BASED, 18 | ShadingType::AXIAL, 19 | ShadingType::RADIAL, 20 | ShadingType::FREE_FORM_TRIANGLE_MESH, 21 | ShadingType::LATTICE_FORM_TRIANGLE_MESH, 22 | ShadingType::COONS_PATCH_MESH, 23 | ShadingType::TENSOR_PRODUCT_PATCH_MESH, 24 | ); 25 | 26 | 27 | /** 28 | * Test if given parameter is a valid shading type. 29 | * 30 | * @param int $value 31 | * @return bool 32 | */ 33 | public static function isValid($value): bool 34 | { 35 | return IntegerValidator::isValid($value) && in_array($value, self::SHADING_TYPES); 36 | } 37 | } -------------------------------------------------------------------------------- /src/Font/FontStretch.php: -------------------------------------------------------------------------------- 1 | width = $width; 32 | return $this; 33 | } 34 | 35 | /** 36 | * Get component's width. 37 | * 38 | * @return float 39 | */ 40 | public function getWidth(): float 41 | { 42 | return $this->width; 43 | } 44 | } -------------------------------------------------------------------------------- /src/Graphics/ShadingType.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const LINE_ENDING_STYLES = array( 17 | LineEndingStyle::NONE, 18 | LineEndingStyle::CLOSED_ARROW, 19 | LineEndingStyle::OPEN_ARROW, 20 | LineEndingStyle::R_CLOSED_ARROW, 21 | LineEndingStyle::R_OPEN_ARROW, 22 | LineEndingStyle::CIRCLE, 23 | LineEndingStyle::BUTT, 24 | LineEndingStyle::DIAMOND, 25 | LineEndingStyle::SLASH, 26 | LineEndingStyle::SQUARE, 27 | ); 28 | 29 | /** 30 | * Test if given parameter is a valid annotation highlight mode. 31 | * 32 | * @param string $value 33 | * @return bool 34 | */ 35 | public static function isValid($value): bool 36 | { 37 | return StringValidator::isValid($value) && in_array($value, self::LINE_ENDING_STYLES); 38 | } 39 | } -------------------------------------------------------------------------------- /src/Component/Height.php: -------------------------------------------------------------------------------- 1 | height = $height; 33 | return $this; 34 | } 35 | 36 | /** 37 | * Get component's height. 38 | * 39 | * @return float 40 | */ 41 | public function getHeight(): float 42 | { 43 | return $this->height; 44 | } 45 | } -------------------------------------------------------------------------------- /src/Type/CalRGBColourSpaceDictionaryType.php: -------------------------------------------------------------------------------- 1 | $matrix 17 | * @return CalRGBColourSpaceDictionaryType 18 | * @throws InvalidArgumentException if the provided argument is not a 9 length array of type 'int' or 'float'. 19 | */ 20 | public function setMatrix(array $matrix): CalRGBColourSpaceDictionaryType 21 | { 22 | if (!NumbersArrayValidator::isValid($matrix, 9)) { 23 | throw new InvalidArgumentException("Matrix is incorrect. See ".__CLASS__." class's documentation for possible values."); 24 | } 25 | 26 | $value = Factory::create('Papier\Type\NumbersArrayType', $matrix); 27 | 28 | $this->setEntry('Matrix', $value); 29 | return $this; 30 | } 31 | } -------------------------------------------------------------------------------- /src/Document/AnnotationFlag.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const FLAGS = array( 17 | FontDescriptorFlag::FIXED_PITCH, 18 | FontDescriptorFlag::SERIF, 19 | FontDescriptorFlag::SYMBOLIC, 20 | FontDescriptorFlag::SCRIPT, 21 | FontDescriptorFlag::NON_SYMBOLIC, 22 | FontDescriptorFlag::ITALIC, 23 | FontDescriptorFlag::ALL_CAP, 24 | FontDescriptorFlag::SMALL_CAP, 25 | FontDescriptorFlag::FORCE_BOLD, 26 | ); 27 | 28 | /** 29 | * Test if given parameter is a valid function type. 30 | * 31 | * @param int $value 32 | * @return bool 33 | */ 34 | public static function isValid($value): bool 35 | { 36 | $bit = 0; 37 | foreach (self::FLAGS as $flag) { 38 | $bit |= ($value & $flag); 39 | } 40 | 41 | return IntegerValidator::isValid($value) && $bit > 0; 42 | } 43 | } -------------------------------------------------------------------------------- /src/Validator/RenderingModeValidator.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const RENDERING_MODES = array( 17 | RenderingMode::FILL, 18 | RenderingMode::STROKE, 19 | RenderingMode::FILL_THEN_STROKE, 20 | RenderingMode::NEITHER_FILL_NOR_STROKE, 21 | RenderingMode::FILL_AND_ADD_TO_PATH, 22 | RenderingMode::STROKE_AND_ADD_TO_PATH, 23 | RenderingMode::FILL_THEN_STROKE_AND_ADD_TO_PATH, 24 | RenderingMode::ADD_TO_PATH, 25 | ); 26 | 27 | 28 | /** 29 | * Test if given parameter is a valid rendering mode. 30 | * 31 | * @param int $value 32 | * @return bool 33 | */ 34 | public static function isValid($value): bool 35 | { 36 | return IntegerValidator::isValid($value) && in_array($value, self::RENDERING_MODES); 37 | } 38 | } -------------------------------------------------------------------------------- /src/Type/DeveloperExtensionDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('BaseVersion', $version); 21 | return $this; 22 | } 23 | 24 | /** 25 | * Set extension level. 26 | * 27 | * @param int $level 28 | * @return DeveloperExtensionDictionaryType 29 | */ 30 | public function setExtensionLevel(int $level): DeveloperExtensionDictionaryType 31 | { 32 | $value = Factory::create('Papier\Type\Base\IntegerType', $level); 33 | 34 | $this->setEntry('ExtensionLevel', $value); 35 | return $this; 36 | } 37 | } -------------------------------------------------------------------------------- /src/Validator/AnnotationFlagValidator.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const ANNOTATION_FLAGS = array( 17 | AnnotationFlag::INVISIBLE, 18 | AnnotationFlag::HIDDEN, 19 | AnnotationFlag::PRINT, 20 | AnnotationFlag::NO_ZOOM, 21 | AnnotationFlag::NO_ROTATE, 22 | AnnotationFlag::NO_VIEW, 23 | AnnotationFlag::READ_ONLY, 24 | AnnotationFlag::LOCKED, 25 | AnnotationFlag::TOGGLE_NO_VIEW, 26 | AnnotationFlag::LOCKED_CONTENTS, 27 | ); 28 | 29 | /** 30 | * Test if given parameter is a valid function type. 31 | * 32 | * @param int $value 33 | * @return bool 34 | */ 35 | public static function isValid($value): bool 36 | { 37 | $bit = 0; 38 | foreach (self::ANNOTATION_FLAGS as $flag) { 39 | $bit |= ($value & $flag); 40 | } 41 | 42 | return IntegerValidator::isValid($value) && $bit > 0; 43 | } 44 | } -------------------------------------------------------------------------------- /src/Type/MediaRenditionDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('C', $c); 18 | return $this; 19 | } 20 | 21 | /** 22 | * Set media play parameters dictionary. 23 | * 24 | * @param DictionaryType $p 25 | * @return MediaRenditionDictionaryType 26 | */ 27 | public function setP(DictionaryType $p): MediaRenditionDictionaryType 28 | { 29 | $this->setEntry('P', $p); 30 | return $this; 31 | } 32 | 33 | /** 34 | * Set media screen parameters dictionary. 35 | * 36 | * @param DictionaryType $sp 37 | * @return MediaRenditionDictionaryType 38 | */ 39 | public function setSP(DictionaryType $sp): MediaRenditionDictionaryType 40 | { 41 | $this->setEntry('SP', $sp); 42 | return $this; 43 | } 44 | } -------------------------------------------------------------------------------- /src/Graphics/RenderingIntent.php: -------------------------------------------------------------------------------- 1 | position--; 16 | if (!$this->valid()) { 17 | // Restore position 18 | $this->position++; 19 | } 20 | } 21 | 22 | /** 23 | * Move to next position. 24 | * 25 | */ 26 | public function next(): void 27 | { 28 | $this->position++; 29 | if (!$this->valid()) { 30 | // Restore position 31 | $this->position--; 32 | } 33 | } 34 | 35 | 36 | /** 37 | * Move to given position. 38 | * 39 | */ 40 | public function moveTo(int $position): void 41 | { 42 | $oldPosition = $this->position; 43 | $this->position = $position; 44 | if (!$this->valid()) { 45 | // Restore position 46 | $this->position = $oldPosition; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /src/Type/NumberTreeDictionaryType.php: -------------------------------------------------------------------------------- 1 | hasEntry('Root')) { 18 | $root = Factory::create('Papier\Type\NumberTreeNodeDictionaryType', null, true)->setRoot(); 19 | $this->setEntry('Root', $root); 20 | } 21 | 22 | /** @var NumberTreeNodeDictionaryType $root */ 23 | $root = $this->getEntry('Root'); 24 | return $root; 25 | } 26 | 27 | /** 28 | * Add number to tree. 29 | * 30 | * @param mixed $object 31 | * @param string $key 32 | * @return NumberTreeDictionaryType 33 | */ 34 | public function addNum(string $key, $object): NumberTreeDictionaryType 35 | { 36 | $this->getRoot()->addNum($key, $object); 37 | return $this; 38 | } 39 | } -------------------------------------------------------------------------------- /src/Type/NameTreeDictionaryType.php: -------------------------------------------------------------------------------- 1 | hasEntry('Root')) { 17 | /** @var NameTreeNodeDictionaryType $root */ 18 | $root = Factory::create('Papier\Type\NameTreeNodeDictionaryType', null, true); 19 | $root->setRoot(); 20 | $this->setEntry('Root', $root); 21 | } 22 | 23 | /** @var NameTreeNodeDictionaryType $root */ 24 | $root = $this->getEntry('Root'); 25 | return $root; 26 | } 27 | 28 | /** 29 | * Add number to tree. 30 | * 31 | * @param string $key 32 | * @param mixed $object 33 | * @return NameTreeDictionaryType 34 | */ 35 | public function addName(string $key, $object): NameTreeDictionaryType 36 | { 37 | $this->getRoot()->addName($key, $object); 38 | return $this; 39 | } 40 | } -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Mikael Carlavan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/Document/PageMode.php: -------------------------------------------------------------------------------- 1 | getObjects(); 27 | 28 | foreach ($value as $i => $val) { 29 | $object = Factory::create('Papier\Type\Base\IntegerType', $val); 30 | $objects[$i] = $object; 31 | } 32 | 33 | parent::setValue($objects); 34 | 35 | return $this; 36 | } 37 | } -------------------------------------------------------------------------------- /src/Type/FileSpecificationStringType.php: -------------------------------------------------------------------------------- 1 | getValue(); 20 | 21 | // Check if network resource is present 22 | if (strpos($value, ':\\') !== false) { 23 | $value = '/'.$value; 24 | $value = str_replace(':\\', '/', $value); 25 | } 26 | 27 | // Check for DOS absolute path 28 | if (substr($value, 0, 1) == '\\') { 29 | $value = '//'.substr($value, 1); 30 | } 31 | 32 | $trans = array('(' => '\(', ')' => '\)', '\\' => '/'); 33 | return strtr($value, $trans); 34 | } 35 | 36 | /** 37 | * Format object's value. 38 | * 39 | * @return string 40 | */ 41 | public function format(): string 42 | { 43 | $value = $this->getConvertedValue(); 44 | return '(' .$value. ')'; 45 | } 46 | } -------------------------------------------------------------------------------- /src/Type/PageLabelsNumberTreeDictionaryType.php: -------------------------------------------------------------------------------- 1 | setS($style); 24 | if (!is_null($prefix)) { 25 | $pageLabel->setP($prefix); 26 | } 27 | if ($start > 0) { 28 | $pageLabel->setSt($start); 29 | } 30 | $object = new PageLabelDictionaryType(); 31 | $this->addNum($page, $pageLabel); 32 | 33 | return $object; 34 | } 35 | } -------------------------------------------------------------------------------- /src/Text/RenderingMode.php: -------------------------------------------------------------------------------- 1 | lineWidth = $lineWidth; 27 | return $this; 28 | } 29 | 30 | /** 31 | * Get line's cap width. 32 | * 33 | * @return float 34 | */ 35 | public function getLineWidth(): float 36 | { 37 | return $this->lineWidth; 38 | } 39 | 40 | /** 41 | * Set line with to content stream. 42 | * 43 | * @param ContentStreamType $contents 44 | * @return static 45 | */ 46 | public function applyWidth(ContentStreamType &$contents): static 47 | { 48 | $lineWidth = $this->getLineWidth(); 49 | if ($lineWidth > 0) { 50 | $contents->setLineWidth(MetricHelper::toUserUnit($lineWidth)); 51 | } 52 | 53 | return $this; 54 | } 55 | } -------------------------------------------------------------------------------- /src/Filter/Predictor.php: -------------------------------------------------------------------------------- 1 | hasEntry('Root')) { 18 | /** @var TreeNodeDictionaryType $root */ 19 | $root = Factory::create('Papier\Type\TreeNodeDictionaryType', null, true); 20 | $root->setRoot(); 21 | $this->setEntry('Root', $root); 22 | } 23 | 24 | /** @var TreeNodeDictionaryType $root */ 25 | $root = $this->getEntry('Root'); 26 | return $root; 27 | } 28 | 29 | /** 30 | * Add kid to tree. 31 | * 32 | * @return TreeNodeDictionaryType 33 | */ 34 | public function addKid(): TreeNodeDictionaryType 35 | { 36 | return $this->getRoot()->addKid(); 37 | } 38 | 39 | /** 40 | * Format object's value. 41 | * 42 | * @return string 43 | */ 44 | public function format(): string 45 | { 46 | $root = $this->getRoot(); 47 | return $root->format(); 48 | } 49 | } -------------------------------------------------------------------------------- /src/File/CrossReferenceTable.php: -------------------------------------------------------------------------------- 1 | getSections(); 18 | 19 | $object = new CrossReferenceSection(); 20 | $objects[] = $object; 21 | 22 | $this->setObjects($objects); 23 | 24 | return $object; 25 | } 26 | 27 | /** 28 | * Get subsections. 29 | * 30 | * @return array 31 | */ 32 | public function getSections(): array 33 | { 34 | /** @var array $objects */ 35 | $objects = $this->getObjects(); 36 | return $objects; 37 | } 38 | 39 | /** 40 | * Format object's value. 41 | * 42 | * @return string 43 | */ 44 | public function format(): string 45 | { 46 | $objects = $this->getSections(); 47 | 48 | $value = ''; 49 | foreach ($objects as $object) { 50 | $value .= $object->write(); 51 | } 52 | 53 | return rtrim($value); 54 | } 55 | } -------------------------------------------------------------------------------- /src/Document/PageLayout.php: -------------------------------------------------------------------------------- 1 | page = $page; 27 | return $this; 28 | } 29 | 30 | /** 31 | * Get component's page. 32 | * 33 | * @return PageObjectDictionaryType 34 | */ 35 | public function getPage(): PageObjectDictionaryType 36 | { 37 | return $this->page; 38 | } 39 | 40 | /** 41 | * Get contents. 42 | * 43 | * @return ContentStreamType 44 | */ 45 | protected function getContents(): ContentStreamType 46 | { 47 | $page = $this->getPage(); 48 | return $page->getContents(); 49 | } 50 | 51 | /** 52 | * Format component's content. 53 | * 54 | * @return BaseComponent 55 | */ 56 | abstract function format(): BaseComponent; 57 | } -------------------------------------------------------------------------------- /src/Filter/FlateFilter.php: -------------------------------------------------------------------------------- 1 | setValue((int)$data); 46 | 47 | return $object; 48 | } 49 | } -------------------------------------------------------------------------------- /src/File/CrossReference/CrossReferenceSection.php: -------------------------------------------------------------------------------- 1 | getSubsections(); 17 | 18 | $object = new CrossReferenceSubSection(); 19 | $objects[] = $object; 20 | 21 | $this->setObjects($objects); 22 | 23 | return $object; 24 | } 25 | 26 | /** 27 | * Get subsections. 28 | * 29 | * @return array 30 | */ 31 | public function getSubsections(): array 32 | { 33 | /** @var array $objects */ 34 | $objects = $this->getObjects(); 35 | return $objects; 36 | } 37 | 38 | /** 39 | * Format object's value. 40 | * 41 | * @return string 42 | */ 43 | public function format(): string 44 | { 45 | $objects = $this->getSubsections(); 46 | 47 | $value = 'xref'. self::EOL_MARKER; 48 | if (count($objects) > 0) { 49 | foreach ($objects as $object) { 50 | $value .= $object->write(); 51 | } 52 | } 53 | 54 | return $value; 55 | } 56 | } -------------------------------------------------------------------------------- /src/Type/HexadecimalStringType.php: -------------------------------------------------------------------------------- 1 | getValue(); 21 | $chars = str_split($value); 22 | 23 | $value = ''; 24 | foreach ($chars as $char) { 25 | $value .= str_pad(dechex(ord($char)), 2, "0", STR_PAD_LEFT); 26 | } 27 | 28 | return '<' .$value. '>'; 29 | } 30 | 31 | /** 32 | * Create object from string. 33 | * 34 | * @param string $data 35 | * @return HexadecimalStringType 36 | */ 37 | public static function fromString(string $data): HexadecimalStringType 38 | { 39 | $object = new HexadecimalStringType(); 40 | 41 | // Clean input: remove < and > 42 | $data = trim($data); 43 | $data = trim($data, '<>'); 44 | 45 | // Normalize possible odd-length hex 46 | if (strlen($data) % 2 !== 0) { 47 | $data .= '0'; 48 | } 49 | 50 | // Convert hex to raw string 51 | $decoded = ''; 52 | for ($i = 0; $i < strlen($data); $i += 2) { 53 | $decoded .= chr(hexdec(substr($data, $i, 2))); 54 | } 55 | 56 | $object->setValue($decoded); 57 | 58 | return $object; 59 | } 60 | } -------------------------------------------------------------------------------- /src/Filter/FilterType.php: -------------------------------------------------------------------------------- 1 | setTimestamp($timestamp); 30 | parent::setValue($date); 31 | } else { 32 | parent::setValue($value); 33 | } 34 | 35 | 36 | return $this; 37 | } 38 | 39 | /** 40 | * Get object's value. 41 | * 42 | * @return string 43 | */ 44 | protected function getValue(): string 45 | { 46 | /** @var DateTime $date */ 47 | $date = parent::getValue(); 48 | 49 | $value = 'D:'.$date->format('YmdHis') . substr_replace($date->format('O'), "'", 3, 0); 50 | return '('.$value.')'; 51 | } 52 | } -------------------------------------------------------------------------------- /src/Object/RealObject.php: -------------------------------------------------------------------------------- 1 | setValue((double)$data); 51 | 52 | return $object; 53 | } 54 | } -------------------------------------------------------------------------------- /src/Graphics/Colour.php: -------------------------------------------------------------------------------- 1 | addToContent($state); 29 | } 30 | 31 | /** 32 | * Set colour for non-stroking operations. 33 | * 34 | * @param mixed $values 35 | * @return mixed 36 | */ 37 | public function setSpecialSpacesNonStrokingColor(...$values) 38 | { 39 | foreach ($values as $value) { 40 | if (!NumberValidator::isValid($value)) { 41 | throw new InvalidArgumentException("Colour is incorrect. See ".__CLASS__." class's documentation for possible values."); 42 | } 43 | } 44 | 45 | $state = sprintf('%s scn', implode(' ', $values)); 46 | return $this->addToContent($state); 47 | } 48 | } -------------------------------------------------------------------------------- /src/Repository/Repository.php: -------------------------------------------------------------------------------- 1 | getObjects(); 40 | $objects[$object->getNumber()] = $object; 41 | $this->setObjects($objects); 42 | return $this; 43 | } 44 | 45 | /** 46 | * Remove object from repository. 47 | * 48 | * @param IndirectObject $object 49 | * @return Repository 50 | */ 51 | public function removeObject(IndirectObject $object): Repository 52 | { 53 | $objects = $this->getObjects(); 54 | unset($objects[$object->getNumber()]); 55 | $this->setObjects($objects); 56 | return $this; 57 | } 58 | } -------------------------------------------------------------------------------- /src/Validator/AnnotationTypeValidator.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | const ANNOTATION_TYPES = array( 17 | AnnotationType::TEXT, 18 | AnnotationType::LINK, 19 | AnnotationType::FREE_TEXT, 20 | AnnotationType::LINE, 21 | AnnotationType::SQUARE, 22 | AnnotationType::CIRCLE, 23 | AnnotationType::POLYGON, 24 | AnnotationType::POLY_LINE, 25 | AnnotationType::HIGHLIGHT, 26 | AnnotationType::UNDERLINE, 27 | AnnotationType::SQUIGGLY, 28 | AnnotationType::STRIKE_OUT, 29 | AnnotationType::STAMP, 30 | AnnotationType::CARET, 31 | AnnotationType::INK, 32 | AnnotationType::POPUP, 33 | AnnotationType::FILE_ATTACHMENT, 34 | AnnotationType::SOUND, 35 | AnnotationType::MOVIE, 36 | AnnotationType::WIDGET, 37 | AnnotationType::SCREEN, 38 | AnnotationType::PRINTER_MARK, 39 | AnnotationType::TRAP_NET, 40 | AnnotationType::WATERMARK, 41 | AnnotationType::THREE_D, 42 | AnnotationType::REDACT, 43 | ); 44 | 45 | 46 | /** 47 | * Test if given parameter is a valid type 48 | * 49 | * @param string $value 50 | * @return bool 51 | */ 52 | public static function isValid($value): bool 53 | { 54 | return StringValidator::isValid($value) && in_array($value, self::ANNOTATION_TYPES); 55 | } 56 | } -------------------------------------------------------------------------------- /src/Type/DeviceNProcessDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('ColorSpace', $value); 30 | return $this; 31 | } 32 | 33 | /** 34 | * Set components. 35 | * 36 | * @param ArrayObject $components 37 | * @return DeviceNProcessDictionaryType 38 | */ 39 | public function setComponents(ArrayObject $components): DeviceNProcessDictionaryType 40 | { 41 | $this->setEntry('Components', $components); 42 | return $this; 43 | } 44 | } -------------------------------------------------------------------------------- /src/File/CrossReference/CrossReferenceSubSection.php: -------------------------------------------------------------------------------- 1 | getEntries(); 17 | 18 | $object = new CrossReferenceEntry(); 19 | $objects[] = $object; 20 | 21 | $this->setObjects($objects); 22 | 23 | return $object; 24 | } 25 | 26 | /** 27 | * Get subsections. 28 | * 29 | * @return array 30 | */ 31 | public function getEntries(): array 32 | { 33 | /** @var array $objects */ 34 | $objects = $this->getObjects(); 35 | return $objects; 36 | } 37 | 38 | /** 39 | * Format object's value. 40 | * 41 | * @return string 42 | */ 43 | public function format(): string 44 | { 45 | $objects = $this->getEntries(); 46 | $firstNumber = 0; 47 | if (count($objects) > 0) { 48 | $firstNumber = $objects[0]->getOffset(); 49 | } 50 | $value = sprintf("%d %d", $firstNumber, count($objects)) . self::EOL_MARKER; 51 | 52 | if (count($objects) > 0) { 53 | foreach ($objects as $object) { 54 | $value .= $object->write(); 55 | } 56 | } 57 | 58 | return $value; 59 | } 60 | } -------------------------------------------------------------------------------- /src/Component/RectangleComponent.php: -------------------------------------------------------------------------------- 1 | getContents(); 25 | $contents->save(); 26 | 27 | $this->applyColors($contents); 28 | 29 | $x = $this->getX(); 30 | $y = $this->getY(); 31 | $width = $this->getWidth(); 32 | $height = $this->getHeight(); 33 | 34 | $lineWidth = $this->getLineWidth(); 35 | 36 | $contents->setLineWidth(MetricHelper::toUserUnit($lineWidth)); 37 | 38 | $contents->appendRectangle(MetricHelper::toUserUnit($x), MetricHelper::toUserUnit($y), MetricHelper::toUserUnit($width), MetricHelper::toUserUnit($height)); 39 | 40 | $strokingColors = $this->getStrokingColor(); 41 | $nonStrokingColors = $this->getNonStrokingColor(); 42 | 43 | if ($strokingColors && $nonStrokingColors) { 44 | $contents->fillAndStroke(); 45 | } else if ($strokingColors) { 46 | $contents->stroke(); 47 | } else { 48 | $contents->fill(); 49 | } 50 | 51 | $contents->restore(); 52 | 53 | return $this; 54 | } 55 | } -------------------------------------------------------------------------------- /src/Component/TableComponent.php: -------------------------------------------------------------------------------- 1 | header = new TableHeadComponent(); 41 | $this->footer = new TableFootComponent(); 42 | $this->body = new TableBodyComponent(); 43 | } 44 | 45 | /** 46 | * Get header. 47 | * 48 | * @return TableHeadComponent 49 | */ 50 | public function getHeader(): TableHeadComponent 51 | { 52 | return $this->header; 53 | } 54 | 55 | /** 56 | * Get body. 57 | * 58 | * @return TableBodyComponent 59 | */ 60 | public function getBody(): TableBodyComponent 61 | { 62 | return $this->body; 63 | } 64 | 65 | /** 66 | * Get trailer. 67 | * 68 | * @return TableFootComponent 69 | */ 70 | public function getFooter(): TableFootComponent 71 | { 72 | return $this->footer; 73 | } 74 | 75 | function format(): TableComponent 76 | { 77 | // TODO: Implement format() method. 78 | } 79 | } -------------------------------------------------------------------------------- /src/Type/CollectionItemDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry($key, $object); 33 | return $this; 34 | } 35 | 36 | /** 37 | * Format object's value. 38 | * 39 | * @return string 40 | */ 41 | public function format(): string 42 | { 43 | $type = Factory::create('Papier\Type\Base\NameType', 'CollectionItem'); 44 | $this->setEntry('Type', $type); 45 | 46 | return parent::format(); 47 | } 48 | } -------------------------------------------------------------------------------- /src/Type/PatternDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('PatternType', $value); 30 | return $this; 31 | } 32 | 33 | /** 34 | * Format object's value. 35 | * 36 | * @return string 37 | */ 38 | public function format(): string 39 | { 40 | if (!$this->hasEntry('PatternType')) { 41 | throw new RuntimeException("PatternType is missing. See ".__CLASS__." class's documentation for possible values."); 42 | } 43 | 44 | $type = Factory::create('Papier\Type\Base\NameType', 'Pattern'); 45 | $this->setEntry('Type', $type); 46 | 47 | return parent::format(); 48 | } 49 | } -------------------------------------------------------------------------------- /src/Type/EmbeddedFileStreamType.php: -------------------------------------------------------------------------------- 1 | setEntry('Subtype', $value); 27 | return $this; 28 | } 29 | 30 | /** 31 | * Set parameters. 32 | * 33 | * @param DictionaryType $params 34 | * @throws InvalidArgumentException if the provided argument is not of type 'DictionaryObject'. 35 | * @return EmbeddedFileStreamType 36 | */ 37 | public function setParams(DictionaryType $params): EmbeddedFileStreamType 38 | { 39 | $this->setEntry('Params', $params); 40 | return $this; 41 | } 42 | 43 | /** 44 | * Format object's value. 45 | * 46 | * @return string 47 | */ 48 | public function format(): string 49 | { 50 | $type = Factory::create('Papier\Type\Base\NameType', 'EmbeddedFile'); 51 | $this->setEntry('Type', $type); 52 | 53 | return parent::format(); 54 | } 55 | } -------------------------------------------------------------------------------- /src/Type/ThreadDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('F', $f); 23 | return $this; 24 | } 25 | 26 | /** 27 | * Set thread information dictionary containing information about the 28 | * thread, such as its title, author, and creation date. 29 | * 30 | * @param DocumentInformationDictionaryType $i 31 | * @return ThreadDictionaryType 32 | * @throws InvalidArgumentException if the provided argument is not of type 'DictionaryObject'. 33 | */ 34 | public function setI(DocumentInformationDictionaryType $i): ThreadDictionaryType 35 | { 36 | $this->setEntry('I', $i); 37 | return $this; 38 | } 39 | 40 | /** 41 | * Format thread's content. 42 | * 43 | * @return string 44 | */ 45 | public function format(): string 46 | { 47 | if (!$this->hasEntry('F')) { 48 | throw new RuntimeException("F is missing. See ".__CLASS__." class's documentation for possible values."); 49 | } 50 | 51 | $type = Factory::create('Papier\Type\Base\NameType', 'Thread'); 52 | $this->setEntry('Type', $type); 53 | 54 | return parent::format(); 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /src/Object/CommentObject.php: -------------------------------------------------------------------------------- 1 | getValue(); 36 | 37 | $trans = array('%' => '\%'); 38 | $value = strtr($value, $trans); 39 | 40 | return '%'.$value; 41 | } 42 | 43 | /** 44 | * Create object from string. 45 | * 46 | * @param string $data 47 | * @return CommentObject 48 | */ 49 | public static function fromString(string $data): CommentObject 50 | { 51 | $object = new CommentObject(); 52 | 53 | // Trim whitespace and leading '%' 54 | $data = trim($data); 55 | $data = ltrim($data, '%'); 56 | 57 | // Unescape escaped percent signs (\%) 58 | $data = str_replace('\%', '%', $data); 59 | 60 | $object->setValue($data); 61 | 62 | return $object; 63 | } 64 | } -------------------------------------------------------------------------------- /src/Type/LatticeFormTriangleMeshShadingDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('VerticesPerRow', $value); 29 | return $this; 30 | } 31 | 32 | /** 33 | * Format object's value. 34 | * 35 | * @return string 36 | */ 37 | public function format(): string 38 | { 39 | if (!$this->hasEntry('VerticesPerRow')) { 40 | throw new RuntimeException("VerticesPerRow is missing. See ".__CLASS__." class's documentation for possible values."); 41 | } 42 | 43 | $this->setEntry('ShadingType', ShadingType::LATTICE_FORM_TRIANGLE_MESH); 44 | return parent::format(); 45 | } 46 | } -------------------------------------------------------------------------------- /src/Filter/ASCIIHexFilter.php: -------------------------------------------------------------------------------- 1 | "; 19 | 20 | /** 21 | * Decode stream. 22 | * 23 | * @param string $stream 24 | * @param DictionaryObject|null $param 25 | * @return string|bool 26 | */ 27 | public static function decode(string $stream, ?DictionaryObject $param = null): string|bool 28 | { 29 | $stream = trim($stream); 30 | $marker = substr($stream, -strlen(self::EOD_MARKER)); 31 | 32 | if ($marker != self::EOD_MARKER) { 33 | throw new InvalidArgumentException("Stream is incorrect. See ".__CLASS__." class's documentation for possible values."); 34 | } 35 | 36 | $stream = substr($stream, 0, -strlen(self::EOD_MARKER)); 37 | 38 | return hex2bin($stream); 39 | } 40 | 41 | /** 42 | * Encode value. 43 | * 44 | * @param string $value 45 | * @param DictionaryObject|null $param 46 | * @return string 47 | */ 48 | public static function encode(string $value, ?DictionaryObject $param = null): string 49 | { 50 | if (!StringValidator::isValid($value)) { 51 | throw new InvalidArgumentException("Value is incorrect. See ".__CLASS__." class's documentation for possible values."); 52 | } 53 | 54 | return bin2hex($value) . self::EOD_MARKER; 55 | } 56 | } -------------------------------------------------------------------------------- /src/Type/OutlineDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('First', $first); 22 | return $this; 23 | } 24 | 25 | /** 26 | * Set last. 27 | * 28 | * @param DictionaryType $last 29 | * @return OutlineDictionaryType 30 | */ 31 | public function setLast(DictionaryType $last): OutlineDictionaryType 32 | { 33 | $this->setEntry('Last', $last); 34 | return $this; 35 | } 36 | 37 | /** 38 | * Set count. 39 | * 40 | * @param int $count 41 | * @return OutlineDictionaryType 42 | */ 43 | public function setCount(int $count): OutlineDictionaryType 44 | { 45 | if (!IntegerValidator::isValid($count, 0)) { 46 | throw new InvalidArgumentException("Count is incorrect. See ".__CLASS__." class's documentation for possible values."); 47 | } 48 | $value = Factory::create('Papier\Type\Base\IntegerType', $count); 49 | 50 | $this->setEntry('Count', $value); 51 | return $this; 52 | } 53 | 54 | /** 55 | * Format object's value. 56 | * 57 | * @return string 58 | */ 59 | public function format(): string 60 | { 61 | $type = Factory::create('Papier\Type\Base\NameType', 'Outlines'); 62 | $this->setEntry('Type', $type); 63 | 64 | return parent::format(); 65 | } 66 | } -------------------------------------------------------------------------------- /src/Type/MediaClipDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('S', $value); 28 | return $this; 29 | } 30 | 31 | /** 32 | * Set name of the media clip. 33 | * 34 | * @param string $n 35 | * @return MediaClipDictionaryType 36 | */ 37 | public function setN(string $n): MediaClipDictionaryType 38 | { 39 | if (!StringValidator::isValid($n)) { 40 | throw new InvalidArgumentException("N is incorrect. See ".__CLASS__." class's documentation for possible values."); 41 | } 42 | 43 | $value = Factory::create('Papier\Type\TextStringType', $n); 44 | $this->setEntry('N', $value); 45 | return $this; 46 | } 47 | 48 | /** 49 | * Format object's value. 50 | * 51 | * @return string 52 | */ 53 | public function format(): string 54 | { 55 | $type = Factory::create('Papier\Type\Base\NameType', 'MediaClip'); 56 | $this->setEntry('Type', $type); 57 | 58 | return parent::format(); 59 | } 60 | } -------------------------------------------------------------------------------- /src/Object/NameObject.php: -------------------------------------------------------------------------------- 1 | getValue(); 32 | 33 | $trans = array( 34 | ' ' => '#20', '(' => '#28', ')' => '#29', '#' => '#23', '<' => '#3C', '>' => '#3E', 35 | '[' => '#5B', ']' => '#5D', '{' => '#7B', '}' => '#7D', '/' => '#2F', '%' => '#25' 36 | ); 37 | 38 | $value = strtr($value, $trans); 39 | 40 | return '/' .$value; 41 | } 42 | 43 | /** 44 | * Create object from string. 45 | * 46 | * @param string $data 47 | * @return NameObject 48 | */ 49 | public static function fromString(string $data): NameObject 50 | { 51 | $object = new NameObject(); 52 | 53 | // Trim whitespace and leading '/' 54 | $data = trim($data); 55 | $data = ltrim($data, '/'); 56 | 57 | // Decode PDF-encoded hex sequences in the name (e.g., #20 → space) 58 | $data = preg_replace_callback('/#([0-9A-Fa-f]{2})/', function ($matches) { 59 | return chr(hexdec($matches[1])); 60 | }, $data); 61 | 62 | $object->setValue($data); 63 | 64 | return $object; 65 | } 66 | } -------------------------------------------------------------------------------- /src/Object/BaseObject.php: -------------------------------------------------------------------------------- 1 | write(); 29 | } 30 | 31 | /** 32 | * Format object's value. 33 | * 34 | * @return string 35 | */ 36 | public function format(): string 37 | { 38 | /** @var string $value */ 39 | $value = $this->getValue(); 40 | return $value; 41 | } 42 | 43 | /** 44 | * Get object's value. 45 | * 46 | * @return mixed 47 | */ 48 | protected function getValue(): mixed 49 | { 50 | return $this->value; 51 | } 52 | 53 | 54 | /** 55 | * Clear object's value. 56 | * 57 | * @return BaseObject 58 | */ 59 | protected function clearValue(): BaseObject 60 | { 61 | return $this->setValue(null); 62 | } 63 | 64 | /** 65 | * Set object's value. 66 | * 67 | * @param mixed $value 68 | * @return BaseObject 69 | */ 70 | protected function setValue(mixed $value): BaseObject 71 | { 72 | $this->value = $value; 73 | return $this; 74 | } 75 | 76 | /** 77 | * Write object's value. 78 | * 79 | * @return string 80 | */ 81 | public function write(): string 82 | { 83 | return $this->format(). self::EOL_MARKER; 84 | } 85 | } -------------------------------------------------------------------------------- /src/Type/MinimumScreenSizeDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('V', $value); 27 | 28 | return $this; 29 | } 30 | 31 | /** 32 | * Set which monitor should be tested against 33 | * 34 | * @param int $m 35 | * @return MinimumScreenSizeDictionaryType 36 | */ 37 | public function setM(int $m): MinimumScreenSizeDictionaryType 38 | { 39 | if (!IntegerValidator::isValid($m)) { 40 | throw new InvalidArgumentException("M is incorrect. See ".__CLASS__." class's documentation for possible values."); 41 | } 42 | 43 | $value = Factory::create('Papier\Type\Base\IntegerType', $m); 44 | 45 | $this->setEntry('M', $value); 46 | 47 | return $this; 48 | } 49 | 50 | 51 | /** 52 | * Format object's value. 53 | * 54 | * @return string 55 | */ 56 | public function format(): string 57 | { 58 | $type = Factory::create('Papier\Type\Base\NameType', 'MinScreenSize'); 59 | $this->setEntry('Type', $type); 60 | 61 | return parent::format(); 62 | } 63 | } -------------------------------------------------------------------------------- /src/Type/BooleansArrayType.php: -------------------------------------------------------------------------------- 1 | getObjects(); 27 | 28 | foreach ($value as $i => $val) { 29 | $object = Factory::create('Papier\Type\Base\BooleanType', $val); 30 | $objects[$i] = $object; 31 | } 32 | 33 | parent::setValue($objects); 34 | return $this; 35 | } 36 | 37 | /** 38 | * Create object from string. 39 | * 40 | * @param string $data 41 | * @return BooleansArrayType 42 | */ 43 | public static function fromString(string $data): BooleansArrayType 44 | { 45 | $object = new BooleansArrayType(); 46 | 47 | // Parse array using parent parser 48 | $array = parent::fromString($data); 49 | 50 | $values = $array->all(); // get raw values 51 | 52 | $boolObjects = []; 53 | foreach ($values as $i => $val) { 54 | $boolObjects[$i] = Factory::create('Papier\Object\BooleanObject', $val); 55 | } 56 | 57 | $object->setValue($boolObjects); 58 | 59 | return $object; 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /src/Type/MinimumBitDepthDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('V', $value); 29 | 30 | return $this; 31 | } 32 | 33 | /** 34 | * Set specifies which monitor the value of V should be tested agains 35 | * 36 | * @param int $m 37 | * @return MinimumBitDepthDictionaryType 38 | */ 39 | public function setM(int $m): MinimumBitDepthDictionaryType 40 | { 41 | if (!IntegerValidator::isValid($m)) { 42 | throw new InvalidArgumentException("M is incorrect. See ".__CLASS__." class's documentation for possible values."); 43 | } 44 | 45 | $value = Factory::create('Papier\Type\Base\IntegerType', $m); 46 | 47 | $this->setEntry('M', $value); 48 | 49 | return $this; 50 | } 51 | 52 | 53 | /** 54 | * Format object's value. 55 | * 56 | * @return string 57 | */ 58 | public function format(): string 59 | { 60 | $type = Factory::create('Papier\Type\Base\NameType', 'MinBitDepth'); 61 | $this->setEntry('Type', $type); 62 | 63 | return parent::format(); 64 | } 65 | } -------------------------------------------------------------------------------- /src/Object/StringObject.php: -------------------------------------------------------------------------------- 1 | getValue(); 36 | 37 | $trans = array('(' => '\(', ')' => '\)', '\\' => '\\\\'); 38 | $value = strtr($value, $trans); 39 | 40 | return $value. ')'; 41 | } 42 | 43 | /** 44 | * Create object from string. 45 | * 46 | * @param string $data 47 | * @return StringObject 48 | */ 49 | public static function fromString(string $data): StringObject 50 | { 51 | $object = new StringObject(); 52 | 53 | // Trim whitespace 54 | $data = trim($data); 55 | 56 | // Remove surrounding parentheses if present 57 | if (preg_match('/^\((.*)\)$/s', $data, $matches)) { 58 | $data = $matches[1]; 59 | } 60 | 61 | // Unescape escaped characters: \(, \), \\ 62 | $data = str_replace(['\\(', '\\)', '\\\\'], ['(', ')', '\\'], $data); 63 | 64 | $object->setValue($data); 65 | 66 | return $object; 67 | } 68 | } -------------------------------------------------------------------------------- /src/Document/LineEndingStyle.php: -------------------------------------------------------------------------------- 1 | setEntry('Solidities', $solidities); 22 | return $this; 23 | } 24 | 25 | /** 26 | * Set printing order. 27 | * 28 | * @param ArrayObject $order 29 | * @return DeviceNMixingHintsDictionaryType 30 | */ 31 | public function setPrintingOrder(ArrayObject $order): DeviceNMixingHintsDictionaryType 32 | { 33 | $this->setEntry('PrintingOrder', $order); 34 | return $this; 35 | } 36 | 37 | /** 38 | * Set dot gain. 39 | * 40 | * @param DictionaryObject $dotgain 41 | * @return DeviceNMixingHintsDictionaryType 42 | */ 43 | public function setDotGain(DictionaryObject $dotgain): DeviceNMixingHintsDictionaryType 44 | { 45 | $this->setEntry('DotGain', $dotgain); 46 | return $this; 47 | } 48 | 49 | /** 50 | * Format object's value. 51 | * 52 | * @return string 53 | */ 54 | public function format(): string 55 | { 56 | if ($this->hasEntry('Solidities') && !$this->hasEntry('PrintingOrder')) { 57 | throw new RuntimeException("PrintingOrder is missing. See ".__CLASS__." class's documentation for possible values."); 58 | } 59 | 60 | return parent::format(); 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /src/Type/DeviceNColourSpaceAttributesDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('Subtype', $value); 21 | return $this; 22 | } 23 | 24 | /** 25 | * Set colorants. 26 | * 27 | * @param DictionaryObject $colorants 28 | * @return DeviceNColourSpaceAttributesDictionaryType 29 | */ 30 | public function setColorants(DictionaryObject $colorants): DeviceNColourSpaceAttributesDictionaryType 31 | { 32 | $this->setEntry('Colorants', $colorants); 33 | return $this; 34 | } 35 | 36 | /** 37 | * Set process. 38 | * 39 | * @param DictionaryObject $process 40 | * @return DeviceNColourSpaceAttributesDictionaryType 41 | */ 42 | public function setProcess(DictionaryObject $process): DeviceNColourSpaceAttributesDictionaryType 43 | { 44 | $this->setEntry('Process', $process); 45 | return $this; 46 | } 47 | 48 | /** 49 | * Set mixing hints. 50 | * 51 | * @param DictionaryObject $mixinghints 52 | * @return DeviceNColourSpaceAttributesDictionaryType 53 | */ 54 | public function setMixingHints(DictionaryObject $mixinghints): DeviceNColourSpaceAttributesDictionaryType 55 | { 56 | $this->setEntry('MixingHints', $mixinghints); 57 | return $this; 58 | } 59 | } -------------------------------------------------------------------------------- /src/Type/ExponentialInterpolationFunctionType.php: -------------------------------------------------------------------------------- 1 | setEntry('C0', $c0); 23 | return $this; 24 | } 25 | 26 | /** 27 | * Set C1 (function result when x = 1.0). 28 | * 29 | * @param ArrayObject $c1 30 | * @return ExponentialInterpolationFunctionType 31 | */ 32 | public function setC1(ArrayObject $c1): ExponentialInterpolationFunctionType 33 | { 34 | $this->setEntry('C1', $c1); 35 | return $this; 36 | } 37 | 38 | /** 39 | * Set interpolation exponent. 40 | * 41 | * @param float $N 42 | * @return ExponentialInterpolationFunctionType 43 | */ 44 | public function setN(float $N): ExponentialInterpolationFunctionType 45 | { 46 | $value = Factory::create('Papier\Type\Base\RealType', $N); 47 | 48 | $this->setEntry('N', $value); 49 | return $this; 50 | } 51 | 52 | /** 53 | * Format object's value. 54 | * 55 | * @return string 56 | */ 57 | public function format(): string 58 | { 59 | $this->setFunctionType(FunType::EXPONENTIAL_INTERPOLATION); 60 | 61 | if (!$this->hasEntry('N')) { 62 | throw new RuntimeException("N is missing. See ".__CLASS__." class's documentation for possible values."); 63 | } 64 | 65 | return parent::format(); 66 | } 67 | } -------------------------------------------------------------------------------- /src/Factory/Factory.php: -------------------------------------------------------------------------------- 1 | $class 29 | * @param mixed|null $value 30 | * @param bool $isIndirect 31 | * @return T 32 | * @throws InvalidArgumentException if the provided type's object does not exist. 33 | */ 34 | public static function create(string $class, mixed $value = null, bool $isIndirect = false) 35 | { 36 | $instance = self::getInstance(); 37 | 38 | if (!class_exists($class)) { 39 | throw new InvalidArgumentException("$class does not exist. See ".__CLASS__." class's documentation for possible values."); 40 | } 41 | 42 | $object = new $class(); 43 | 44 | if ($isIndirect && $object instanceof IndirectObject) { 45 | $object->setNumber($instance::$number); 46 | $object->setIndirect(); 47 | $instance::$number++; 48 | } 49 | 50 | if (!is_null($value)) { 51 | /** @phpstan-ignore method.nonObject */ 52 | $object->setValue($value); 53 | } 54 | 55 | 56 | return $object; 57 | } 58 | 59 | /** 60 | * Get instance of factory. 61 | * 62 | * @return Factory 63 | */ 64 | private static function getInstance(): Factory 65 | { 66 | if (is_null(self::$instance)) { 67 | self::$instance = new Factory(); 68 | } 69 | 70 | return self::$instance; 71 | } 72 | } -------------------------------------------------------------------------------- /src/Type/PageLabelDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('S', $value); 29 | return $this; 30 | } 31 | 32 | /** 33 | * Set label prefix for page labels in this range. 34 | * 35 | * @param string $p 36 | * @return PageLabelDictionaryType 37 | */ 38 | public function setP(string $p): PageLabelDictionaryType 39 | { 40 | if (!StringValidator::isValid($p)) { 41 | throw new InvalidArgumentException("P is incorrect. See ".__CLASS__." class's documentation for possible values."); 42 | } 43 | 44 | $value = Factory::create('Papier\Type\TextStringType', $p); 45 | $this->setEntry('P', $value); 46 | return $this; 47 | } 48 | 49 | /** 50 | * Set label prefix for page labels in this range. 51 | * 52 | * @param int $st 53 | * @return PageLabelDictionaryType 54 | */ 55 | public function setSt(int $st): PageLabelDictionaryType 56 | { 57 | if (!IntegerValidator::isValid($st, 1)) { 58 | throw new InvalidArgumentException("St is incorrect. See ".__CLASS__." class's documentation for possible values."); 59 | } 60 | 61 | $value = Factory::create('Papier\Type\Base\IntegerType', $st); 62 | $this->setEntry('St', $value); 63 | return $this; 64 | } 65 | } -------------------------------------------------------------------------------- /src/Type/NumbersArrayType.php: -------------------------------------------------------------------------------- 1 | getObjects(); 25 | 26 | /** @var array $value */ 27 | foreach ($value as $i => $val) { 28 | $object = Factory::create('Papier\Type\NumberType', $val); 29 | $objects[$i] = $object; 30 | } 31 | 32 | parent::setValue($objects); 33 | return $this; 34 | } 35 | 36 | /** 37 | * Create object from string. 38 | * 39 | * @param string $data 40 | * @return NumbersArrayType 41 | */ 42 | public static function fromString(string $data): NumbersArrayType 43 | { 44 | // Start from parent ArrayType parser 45 | /** @var ArrayType $arrayObject */ 46 | $arrayObject = parent::fromString($data); 47 | 48 | // Get parsed objects (likely as raw strings or generic base objects) 49 | $objects = $arrayObject->getObjects(); 50 | $converted = []; 51 | 52 | foreach ($objects as $i => $obj) { 53 | $value = is_object($obj) && method_exists($obj, 'getValue') 54 | ? $obj->getValue() 55 | : (float) $obj; 56 | 57 | // Create NumberType for each item 58 | $converted[$i] = Factory::create('Papier\Type\NumberType', $value); 59 | } 60 | 61 | /** @var NumbersArrayType $object */ 62 | $object = Factory::create('Papier\Type\NumbersArrayType'); 63 | $object->setValue($converted); 64 | 65 | return $object; 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /src/Text/Encoding.php: -------------------------------------------------------------------------------- 1 | |false $characters */ 50 | $characters = unpack("C*", $value); 51 | if ($characters) { 52 | while ($i <= count($characters)) { 53 | $firstByteCharacter = $characters[$i++]; 54 | 55 | if ($firstByteCharacter >= 192) { // 192 is 0xC0 = 1100 0000 56 | $secondByteCharacter = $characters[$i++]; 57 | 58 | if ($firstByteCharacter >= 224) { // 224 is 0xE0 = 1110 0000 59 | $thirdByteCharacter = $characters[$i++]; 60 | $out .= chr((($firstByteCharacter & 0x0F) << 4) + (($secondByteCharacter & 0x3C) >> 2)); 61 | $out .= chr((($secondByteCharacter & 0x03) << 6) + ($thirdByteCharacter & 0x3F)); 62 | } else { 63 | $out .= chr(($firstByteCharacter & 0x1C) >> 2); 64 | $out .= chr((($firstByteCharacter & 0x03) << 6) + ($secondByteCharacter & 0x3F)); 65 | } 66 | } else { 67 | $out .= "\0".chr($firstByteCharacter); 68 | } 69 | } 70 | } 71 | 72 | 73 | return $out; 74 | } 75 | } -------------------------------------------------------------------------------- /src/Type/ByteStringsArrayType.php: -------------------------------------------------------------------------------- 1 | getObjects(); 27 | 28 | foreach ($value as $i => $val) { 29 | // Each element is an individual byte string 30 | $object = Factory::create('Papier\Type\Base\ByteStringType', $val); 31 | $objects[$i] = $object; 32 | } 33 | 34 | parent::setValue($objects); 35 | return $this; 36 | } 37 | 38 | /** 39 | * Create object from string. 40 | * 41 | * @param string $data 42 | * @return ByteStringsArrayType 43 | */ 44 | public static function fromString(string $data): ByteStringsArrayType 45 | { 46 | // Parse array using parent ArrayType parser 47 | /** @var ArrayType $arrayObject */ 48 | $arrayObject = parent::fromString($data); 49 | 50 | // Convert each item to a ByteStringType 51 | $objects = $arrayObject->getObjects(); 52 | $converted = []; 53 | 54 | foreach ($objects as $i => $obj) { 55 | $value = is_object($obj) && method_exists($obj, 'getValue') 56 | ? $obj->getValue() 57 | : (string) $obj; 58 | 59 | $converted[$i] = Factory::create('Papier\Type\ByteStringType', $value); 60 | } 61 | 62 | /** @var ByteStringsArrayType $instance */ 63 | $object = Factory::create('Papier\Type\ByteStringsArrayType'); 64 | $object->setValue($converted); 65 | 66 | return $object; 67 | } 68 | } -------------------------------------------------------------------------------- /src/Type/CollectionSubItemDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('D', $value); 35 | return $this; 36 | } 37 | 38 | /** 39 | * Set prefix. 40 | * 41 | * @param string $p 42 | * @return CollectionSubItemDictionaryType 43 | * @throws InvalidArgumentException if the provided argument is not of type 'string'. 44 | */ 45 | public function setP(string $p): CollectionSubItemDictionaryType 46 | { 47 | $value = Factory::create('Papier\Type\TextStringType', $p); 48 | 49 | $this->setEntry('P', $value); 50 | return $this; 51 | } 52 | 53 | /** 54 | * Format object's value. 55 | * 56 | * @return string 57 | */ 58 | public function format(): string 59 | { 60 | $type = Factory::create('Papier\Type\Base\NameType', 'CollectionSubitem'); 61 | $this->setEntry('Type', $type); 62 | 63 | return parent::format(); 64 | } 65 | } -------------------------------------------------------------------------------- /src/Type/RenditionDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('S', $value); 27 | 28 | return $this; 29 | } 30 | 31 | /** 32 | * Set rendition name. 33 | * 34 | * @param string $N 35 | * @return RenditionDictionaryType 36 | */ 37 | public function setN(string $N): RenditionDictionaryType 38 | { 39 | $value = Factory::create('Papier\Type\Base\NameType', $N); 40 | $this->setEntry('N', $value); 41 | return $this; 42 | } 43 | 44 | /** 45 | * Set "mush-honored" parameters. 46 | * 47 | * @param DictionaryType $MH 48 | * @return RenditionDictionaryType 49 | */ 50 | public function setMH(DictionaryType $MH): RenditionDictionaryType 51 | { 52 | $this->setEntry('MH', $MH); 53 | return $this; 54 | } 55 | 56 | /** 57 | * Set "best-effort" parameters. 58 | * 59 | * @param DictionaryType $BE 60 | * @return RenditionDictionaryType 61 | */ 62 | public function setBE(DictionaryType $BE): RenditionDictionaryType 63 | { 64 | $this->setEntry('BE', $BE); 65 | return $this; 66 | } 67 | 68 | /** 69 | * Format object's value. 70 | * 71 | * @return string 72 | */ 73 | public function format(): string 74 | { 75 | $type = Factory::create('Papier\Type\Base\NameType', 'Rendition'); 76 | $this->setEntry('Type', $type); 77 | 78 | return parent::format(); 79 | } 80 | } -------------------------------------------------------------------------------- /src/Type/MacOSFileInformationDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('Subtype', $value); 35 | return $this; 36 | } 37 | 38 | /** 39 | * Set creator. 40 | * 41 | * @param string $creator 42 | * @return MacOSFileInformationDictionaryType 43 | * @throws InvalidArgumentException if the provided argument is not of type 'string'. 44 | */ 45 | public function setCreator(string $creator): MacOSFileInformationDictionaryType 46 | { 47 | $hex = ''; 48 | foreach (str_split($creator) as $s) { 49 | $hex.= dechex(ord($s)); 50 | } 51 | 52 | $value = Factory::create('Papier\Type\Base\IntegerType', hexdec($hex)); 53 | 54 | $this->setEntry('Creator', $value); 55 | return $this; 56 | } 57 | 58 | /** 59 | * Set binary content of resource fork. 60 | * 61 | * @param StreamObject $resfork 62 | * @throws InvalidArgumentException if the provided argument is not of type 'StreamObject'. 63 | * @return MacOSFileInformationDictionaryType 64 | */ 65 | public function setResFork(StreamObject $resfork): MacOSFileInformationDictionaryType 66 | { 67 | $this->setEntry('ResFork', $resfork); 68 | return $this; 69 | } 70 | } -------------------------------------------------------------------------------- /src/Type/ShadingPatternDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('Shading', $shading); 25 | return $this; 26 | } 27 | 28 | 29 | /** 30 | * Set pattern matrix. 31 | * 32 | * @param array $matrix 33 | * @return ShadingPatternDictionaryType 34 | * @throws InvalidArgumentException if the provided argument is not of type 'array'. 35 | */ 36 | public function setMatrix(array $matrix): ShadingPatternDictionaryType 37 | { 38 | if (!NumbersArrayValidator::isValid($matrix, 6)) { 39 | throw new InvalidArgumentException("Matrix is incorrect. See ".__CLASS__." class's documentation for possible values."); 40 | } 41 | 42 | $value = Factory::create('Papier\Type\Base\ArrayType', $matrix); 43 | 44 | $this->setEntry('Matrix', $value); 45 | return $this; 46 | } 47 | 48 | /** 49 | * Set graphics state parameter dictionary. 50 | * 51 | * @param DictionaryObject $extgstate 52 | * @return ShadingPatternDictionaryType 53 | */ 54 | public function setExtGState(DictionaryObject $extgstate): ShadingPatternDictionaryType 55 | { 56 | $this->setEntry('ExtGState', $extgstate); 57 | return $this; 58 | } 59 | 60 | /** 61 | * Format object's value. 62 | * 63 | * @return string 64 | */ 65 | public function format(): string 66 | { 67 | $this->setPatternType(PatternType::SHADING_PATTERN); 68 | 69 | if (!$this->hasEntry('Shading')) { 70 | throw new RuntimeException("Shading is missing. See ".__CLASS__." class's documentation for possible values."); 71 | } 72 | 73 | return parent::format(); 74 | } 75 | } -------------------------------------------------------------------------------- /src/Component/Position.php: -------------------------------------------------------------------------------- 1 | x = $x; 38 | return $this; 39 | } 40 | 41 | /** 42 | * Set component's vertical position. 43 | * 44 | * @param float $y 45 | * @return static 46 | * @throws InvalidArgumentException if the provided argument is not of type 'float' or 'int' and positive. 47 | */ 48 | public function setY(float $y): static 49 | { 50 | if (!NumberValidator::isValid($y, 0.0)) { 51 | throw new InvalidArgumentException("Y is incorrect. See ".__CLASS__." class's documentation for possible values."); 52 | } 53 | 54 | $this->y = $y; 55 | return $this; 56 | } 57 | 58 | 59 | /** 60 | * Set component's position. 61 | * 62 | * @param float $x 63 | * @param float $y 64 | * @return static 65 | * @throws InvalidArgumentException if the provided arguments are not of type 'float' or 'int' and positive. 66 | */ 67 | public function setXY(float $x, float $y): static 68 | { 69 | return $this->setX($x)->setY($y); 70 | } 71 | 72 | /** 73 | * Get component's horizontal position. 74 | * 75 | * @return float 76 | */ 77 | public function getX(): float 78 | { 79 | return $this->x; 80 | } 81 | 82 | /** 83 | * Get component's vertical position. 84 | * 85 | * @return float 86 | */ 87 | public function getY(): float 88 | { 89 | return $this->y; 90 | } 91 | } -------------------------------------------------------------------------------- /src/File/FileHeader.php: -------------------------------------------------------------------------------- 1 | getVersion()); 34 | if ($this->hasBinaryData()) { 35 | $chars = array_map('chr', range(128, 131)); 36 | $comment = Factory::create('Papier\Type\Base\CommentType', implode('', $chars)); 37 | $value .= $comment->format(); 38 | } 39 | return $value; 40 | } 41 | 42 | /** 43 | * Get header's version. 44 | * 45 | * @return int 46 | */ 47 | protected function getVersion(): int 48 | { 49 | $value = $this->getValue(); 50 | return is_int($value) ? $value : self::DEFAULT_VERSION; 51 | } 52 | 53 | /** 54 | * Set header's version. 55 | * 56 | * @param int $version 57 | * @return FileHeader 58 | * @throws InvalidArgumentException if the provided argument is not of type 'int' or is outside acceptable values. 59 | */ 60 | public function setVersion(int $version): FileHeader 61 | { 62 | if (!VersionValidator::isValid($version)) { 63 | throw new InvalidArgumentException("Version is incorrect. See ".__CLASS__." class's documentation for possible values."); 64 | } 65 | 66 | $this->setValue($version); 67 | return $this; 68 | } 69 | 70 | /** 71 | * Get if file has binary data. 72 | * 73 | * @return bool 74 | */ 75 | protected function hasBinaryData(): bool 76 | { 77 | return $this->binaryData; 78 | } 79 | 80 | /** 81 | * Set if file has binary data. 82 | * 83 | * @param bool $binaryData 84 | * @return FileHeader 85 | */ 86 | public function setBinaryData(bool $binaryData): FileHeader 87 | { 88 | $this->binaryData = $binaryData; 89 | return $this; 90 | } 91 | } -------------------------------------------------------------------------------- /src/Type/TextAnnotationDictionaryType.php: -------------------------------------------------------------------------------- 1 | setEntry('Open', $value); 28 | return $this; 29 | } 30 | 31 | /** 32 | * Set name of an icon that shall be used in displaying the 33 | * annotation 34 | * 35 | * @param string $name 36 | * @return TextAnnotationDictionaryType 37 | * @throws InvalidArgumentException if the provided argument is not of type 'string'. 38 | */ 39 | public function setName(string $name): TextAnnotationDictionaryType 40 | { 41 | if (!StringValidator::isValid($name)) { 42 | throw new InvalidArgumentException("Name is incorrect. See ".__CLASS__." class's documentation for possible values."); 43 | } 44 | $value = Factory::create('Papier\Type\Base\NameType', $name); 45 | 46 | $this->setEntry('Name', $value); 47 | return $this; 48 | } 49 | 50 | /** 51 | * Set state to which the original annotation shall be set 52 | * 53 | * @param AnnotationState $state 54 | * @return TextAnnotationDictionaryType 55 | */ 56 | public function setState(AnnotationState $state): TextAnnotationDictionaryType 57 | { 58 | $value = Factory::create('Papier\Type\TextStringType', $state::STATE); 59 | $this->setEntry('State', $value); 60 | 61 | $value = Factory::create('Papier\Type\TextStringType', $state::STATE_MODEL); 62 | $this->setEntry('StateModel', $value); 63 | 64 | return $this; 65 | } 66 | 67 | /** 68 | * Format object's value. 69 | * 70 | * @return string 71 | */ 72 | public function format(): string 73 | { 74 | $type = Factory::create('Papier\Type\Base\NameType', 'Text'); 75 | $this->setEntry('Subtype', $type); 76 | 77 | return parent::format(); 78 | } 79 | } --------------------------------------------------------------------------------