github.com/pdfcpu/pdfcpu@v0.11.1/pkg/api/box.go (about)

     1  /*
     2  Copyright 2020 The pdfcpu Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package api
    18  
    19  import (
    20  	"io"
    21  	"os"
    22  
    23  	"github.com/pdfcpu/pdfcpu/pkg/log"
    24  	"github.com/pdfcpu/pdfcpu/pkg/pdfcpu/model"
    25  	"github.com/pdfcpu/pdfcpu/pkg/pdfcpu/types"
    26  	"github.com/pkg/errors"
    27  )
    28  
    29  // PageBoundariesFromBoxList parses a list of box types.
    30  func PageBoundariesFromBoxList(s string) (*model.PageBoundaries, error) {
    31  	return model.ParseBoxList(s)
    32  }
    33  
    34  // PageBoundaries parses a list of box definitions and assignments.
    35  func PageBoundaries(s string, unit types.DisplayUnit) (*model.PageBoundaries, error) {
    36  	return model.ParsePageBoundaries(s, unit)
    37  }
    38  
    39  // Box parses a box definition.
    40  func Box(s string, u types.DisplayUnit) (*model.Box, error) {
    41  	return model.ParseBox(s, u)
    42  }
    43  
    44  // Boxes returns rs's page boundaries for selected pages of rs.
    45  func Boxes(rs io.ReadSeeker, selectedPages []string, conf *model.Configuration) ([]model.PageBoundaries, error) {
    46  	if rs == nil {
    47  		return nil, errors.New("pdfcpu: Boxes: missing rs")
    48  	}
    49  
    50  	if conf == nil {
    51  		conf = model.NewDefaultConfiguration()
    52  	}
    53  	conf.Cmd = model.LISTBOXES
    54  
    55  	ctx, err := ReadValidateAndOptimize(rs, conf)
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  
    60  	pages, err := PagesForPageSelection(ctx.PageCount, selectedPages, true, true)
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  
    65  	return ctx.PageBoundaries(pages)
    66  }
    67  
    68  // AddBoxes adds page boundaries for selected pages of rs and writes result to w.
    69  func AddBoxes(rs io.ReadSeeker, w io.Writer, selectedPages []string, pb *model.PageBoundaries, conf *model.Configuration) error {
    70  	if rs == nil {
    71  		return errors.New("pdfcpu: AddBoxes: missing rs")
    72  	}
    73  
    74  	if conf == nil {
    75  		conf = model.NewDefaultConfiguration()
    76  	}
    77  	conf.Cmd = model.ADDBOXES
    78  
    79  	ctx, err := ReadValidateAndOptimize(rs, conf)
    80  	if err != nil {
    81  		return err
    82  	}
    83  
    84  	pages, err := PagesForPageSelection(ctx.PageCount, selectedPages, true, true)
    85  	if err != nil {
    86  		return err
    87  	}
    88  
    89  	if err = ctx.AddPageBoundaries(pages, pb); err != nil {
    90  		return err
    91  	}
    92  
    93  	return Write(ctx, w, conf)
    94  }
    95  
    96  // AddBoxesFile adds page boundaries for selected pages of inFile and writes result to outFile.
    97  func AddBoxesFile(inFile, outFile string, selectedPages []string, pb *model.PageBoundaries, conf *model.Configuration) (err error) {
    98  	var f1, f2 *os.File
    99  	if log.CLIEnabled() {
   100  		log.CLI.Printf("adding %s for %s\n", pb, inFile)
   101  	}
   102  
   103  	if f1, err = os.Open(inFile); err != nil {
   104  		return err
   105  	}
   106  
   107  	tmpFile := inFile + ".tmp"
   108  	if outFile != "" && inFile != outFile {
   109  		tmpFile = outFile
   110  		logWritingTo(outFile)
   111  	} else {
   112  		logWritingTo(inFile)
   113  	}
   114  
   115  	if f2, err = os.Create(tmpFile); err != nil {
   116  		f1.Close()
   117  		return err
   118  	}
   119  
   120  	defer func() {
   121  		if err != nil {
   122  			f2.Close()
   123  			f1.Close()
   124  			os.Remove(tmpFile)
   125  			return
   126  		}
   127  		if err = f2.Close(); err != nil {
   128  			return
   129  		}
   130  		if err = f1.Close(); err != nil {
   131  			return
   132  		}
   133  		if outFile == "" || inFile == outFile {
   134  			err = os.Rename(tmpFile, inFile)
   135  		}
   136  	}()
   137  
   138  	return AddBoxes(f1, f2, selectedPages, pb, conf)
   139  }
   140  
   141  // RemoveBoxes removes page boundaries as specified in pb for selected pages of rs and writes result to w.
   142  func RemoveBoxes(rs io.ReadSeeker, w io.Writer, selectedPages []string, pb *model.PageBoundaries, conf *model.Configuration) error {
   143  	if rs == nil {
   144  		return errors.New("pdfcpu: RemoveBoxes: missing rs")
   145  	}
   146  
   147  	if conf == nil {
   148  		conf = model.NewDefaultConfiguration()
   149  	}
   150  	conf.Cmd = model.REMOVEBOXES
   151  
   152  	ctx, err := ReadValidateAndOptimize(rs, conf)
   153  	if err != nil {
   154  		return err
   155  	}
   156  
   157  	pages, err := PagesForPageSelection(ctx.PageCount, selectedPages, true, true)
   158  	if err != nil {
   159  		return err
   160  	}
   161  
   162  	if err = ctx.RemovePageBoundaries(pages, pb); err != nil {
   163  		return err
   164  	}
   165  
   166  	return Write(ctx, w, conf)
   167  }
   168  
   169  // RemoveBoxesFile removes page boundaries as specified in pb for selected pages of inFile and writes result to outFile.
   170  func RemoveBoxesFile(inFile, outFile string, selectedPages []string, pb *model.PageBoundaries, conf *model.Configuration) (err error) {
   171  	var f1, f2 *os.File
   172  
   173  	if log.CLIEnabled() {
   174  		log.CLI.Printf("removing %s for %s\n", pb, inFile)
   175  	}
   176  
   177  	if f1, err = os.Open(inFile); err != nil {
   178  		return err
   179  	}
   180  
   181  	tmpFile := inFile + ".tmp"
   182  	if outFile != "" && inFile != outFile {
   183  		tmpFile = outFile
   184  		logWritingTo(outFile)
   185  	} else {
   186  		logWritingTo(inFile)
   187  	}
   188  
   189  	if f2, err = os.Create(tmpFile); err != nil {
   190  		f1.Close()
   191  		return err
   192  	}
   193  
   194  	defer func() {
   195  		if err != nil {
   196  			f2.Close()
   197  			f1.Close()
   198  			os.Remove(tmpFile)
   199  			return
   200  		}
   201  		if err = f2.Close(); err != nil {
   202  			return
   203  		}
   204  		if err = f1.Close(); err != nil {
   205  			return
   206  		}
   207  		if outFile == "" || inFile == outFile {
   208  			err = os.Rename(tmpFile, inFile)
   209  		}
   210  	}()
   211  
   212  	return RemoveBoxes(f1, f2, selectedPages, pb, conf)
   213  }
   214  
   215  // Crop adds crop boxes for selected pages of rs and writes result to w.
   216  func Crop(rs io.ReadSeeker, w io.Writer, selectedPages []string, b *model.Box, conf *model.Configuration) error {
   217  	if rs == nil {
   218  		return errors.New("pdfcpu: Crop: missing rs")
   219  	}
   220  
   221  	if conf == nil {
   222  		conf = model.NewDefaultConfiguration()
   223  	}
   224  	conf.Cmd = model.CROP
   225  
   226  	ctx, err := ReadValidateAndOptimize(rs, conf)
   227  	if err != nil {
   228  		return err
   229  	}
   230  
   231  	pages, err := PagesForPageSelection(ctx.PageCount, selectedPages, true, true)
   232  	if err != nil {
   233  		return err
   234  	}
   235  
   236  	if err = ctx.Crop(pages, b); err != nil {
   237  		return err
   238  	}
   239  
   240  	return Write(ctx, w, conf)
   241  }
   242  
   243  // CropFile adds crop boxes for selected pages of inFile and writes result to outFile.
   244  func CropFile(inFile, outFile string, selectedPages []string, b *model.Box, conf *model.Configuration) (err error) {
   245  	var f1, f2 *os.File
   246  
   247  	if log.CLIEnabled() {
   248  		log.CLI.Printf("cropping %s\n", inFile)
   249  	}
   250  
   251  	if f1, err = os.Open(inFile); err != nil {
   252  		return err
   253  	}
   254  
   255  	tmpFile := inFile + ".tmp"
   256  	if outFile != "" && inFile != outFile {
   257  		tmpFile = outFile
   258  		logWritingTo(outFile)
   259  	} else {
   260  		logWritingTo(inFile)
   261  	}
   262  
   263  	if f2, err = os.Create(tmpFile); err != nil {
   264  		f1.Close()
   265  		return err
   266  	}
   267  
   268  	defer func() {
   269  		if err != nil {
   270  			f2.Close()
   271  			f1.Close()
   272  			os.Remove(tmpFile)
   273  			return
   274  		}
   275  		if err = f2.Close(); err != nil {
   276  			return
   277  		}
   278  		if err = f1.Close(); err != nil {
   279  			return
   280  		}
   281  		if outFile == "" || inFile == outFile {
   282  			err = os.Rename(tmpFile, inFile)
   283  		}
   284  	}()
   285  
   286  	if conf == nil {
   287  		conf = model.NewDefaultConfiguration()
   288  	}
   289  	conf.Cmd = model.CROP
   290  
   291  	return Crop(f1, f2, selectedPages, b, conf)
   292  }