github.com/unidoc/unidoc@v2.2.0+incompatible/pdf/model/shading.go (about) 1 /* 2 * This file is subject to the terms and conditions defined in 3 * file 'LICENSE.md', which is part of this source code package. 4 */ 5 6 package model 7 8 import ( 9 "errors" 10 11 "github.com/unidoc/unidoc/common" 12 . "github.com/unidoc/unidoc/pdf/core" 13 ) 14 15 // There are 7 types of shading, indicated by the shading type variable: 16 // 1: Function-based shading. 17 // 2: Axial shading. 18 // 3: Radial shading. 19 // 4: Free-form Gouraud-shaded triangle mesh. 20 // 5: Lattice-form Gouraud-shaded triangle mesh. 21 // 6: Coons patch mesh. 22 // 7: Tensor-product patch mesh. 23 // types 4-7 are contained in a stream object, where the dictionary is given by the stream dictionary. 24 type PdfShading struct { 25 ShadingType *PdfObjectInteger 26 ColorSpace PdfColorspace 27 Background *PdfObjectArray 28 BBox *PdfRectangle 29 AntiAlias *PdfObjectBool 30 31 context PdfModel // The sub shading type entry (types 1-7). Represented by PdfShadingType1-7. 32 container PdfObject // The container. Can be stream, indirect object, or dictionary. 33 } 34 35 func (this *PdfShading) GetContainingPdfObject() PdfObject { 36 return this.container 37 } 38 39 // Context in this case is a reference to the subshading entry as represented by PdfShadingType1-7. 40 func (this *PdfShading) GetContext() PdfModel { 41 return this.context 42 } 43 44 // Set the sub annotation (context). 45 func (this *PdfShading) SetContext(ctx PdfModel) { 46 this.context = ctx 47 } 48 49 func (this *PdfShading) getShadingDict() (*PdfObjectDictionary, error) { 50 obj := this.container 51 52 if indObj, isInd := obj.(*PdfIndirectObject); isInd { 53 d, ok := indObj.PdfObject.(*PdfObjectDictionary) 54 if !ok { 55 return nil, ErrTypeError 56 } 57 58 return d, nil 59 } else if streamObj, isStream := obj.(*PdfObjectStream); isStream { 60 return streamObj.PdfObjectDictionary, nil 61 } else if d, isDict := obj.(*PdfObjectDictionary); isDict { 62 return d, nil 63 } else { 64 common.Log.Debug("Unable to access shading dictionary") 65 return nil, ErrTypeError 66 } 67 } 68 69 // Shading type 1: Function-based shading. 70 type PdfShadingType1 struct { 71 *PdfShading 72 Domain *PdfObjectArray 73 Matrix *PdfObjectArray 74 Function []PdfFunction 75 } 76 77 // Shading type 2: Axial shading. 78 type PdfShadingType2 struct { 79 *PdfShading 80 Coords *PdfObjectArray 81 Domain *PdfObjectArray 82 Function []PdfFunction 83 Extend *PdfObjectArray 84 } 85 86 // Shading type 3: Radial shading. 87 type PdfShadingType3 struct { 88 *PdfShading 89 Coords *PdfObjectArray 90 Domain *PdfObjectArray 91 Function []PdfFunction 92 Extend *PdfObjectArray 93 } 94 95 // Shading type 4: Free-form Gouraud-shaded triangle mesh. 96 type PdfShadingType4 struct { 97 *PdfShading 98 BitsPerCoordinate *PdfObjectInteger 99 BitsPerComponent *PdfObjectInteger 100 BitsPerFlag *PdfObjectInteger 101 Decode *PdfObjectArray 102 Function []PdfFunction 103 } 104 105 // Shading type 5: Lattice-form Gouraud-shaded triangle mesh. 106 type PdfShadingType5 struct { 107 *PdfShading 108 BitsPerCoordinate *PdfObjectInteger 109 BitsPerComponent *PdfObjectInteger 110 VerticesPerRow *PdfObjectInteger 111 Decode *PdfObjectArray 112 Function []PdfFunction 113 } 114 115 // Shading type 6: Coons patch mesh. 116 type PdfShadingType6 struct { 117 *PdfShading 118 BitsPerCoordinate *PdfObjectInteger 119 BitsPerComponent *PdfObjectInteger 120 BitsPerFlag *PdfObjectInteger 121 Decode *PdfObjectArray 122 Function []PdfFunction 123 } 124 125 // Shading type 7: Tensor-product patch mesh. 126 type PdfShadingType7 struct { 127 *PdfShading 128 BitsPerCoordinate *PdfObjectInteger 129 BitsPerComponent *PdfObjectInteger 130 BitsPerFlag *PdfObjectInteger 131 Decode *PdfObjectArray 132 Function []PdfFunction 133 } 134 135 // Used for PDF parsing. Loads the PDF shading from a PDF object. 136 // Can be either an indirect object (types 1-3) containing the dictionary, or a stream object with the stream 137 // dictionary containing the shading dictionary (types 4-7). 138 func newPdfShadingFromPdfObject(obj PdfObject) (*PdfShading, error) { 139 shading := &PdfShading{} 140 141 var dict *PdfObjectDictionary 142 if indObj, isInd := obj.(*PdfIndirectObject); isInd { 143 shading.container = indObj 144 145 d, ok := indObj.PdfObject.(*PdfObjectDictionary) 146 if !ok { 147 common.Log.Debug("Object not a dictionary type") 148 return nil, ErrTypeError 149 } 150 151 dict = d 152 } else if streamObj, isStream := obj.(*PdfObjectStream); isStream { 153 shading.container = streamObj 154 dict = streamObj.PdfObjectDictionary 155 } else if d, isDict := obj.(*PdfObjectDictionary); isDict { 156 shading.container = d 157 dict = d 158 } else { 159 common.Log.Debug("Object type unexpected (%T)", obj) 160 return nil, ErrTypeError 161 } 162 163 if dict == nil { 164 common.Log.Debug("Dictionary missing") 165 return nil, errors.New("Dict missing") 166 } 167 168 // Shading type (required). 169 obj = dict.Get("ShadingType") 170 if obj == nil { 171 common.Log.Debug("Required shading type missing") 172 return nil, ErrRequiredAttributeMissing 173 } 174 obj = TraceToDirectObject(obj) 175 shadingType, ok := obj.(*PdfObjectInteger) 176 if !ok { 177 common.Log.Debug("Invalid type for shading type (%T)", obj) 178 return nil, ErrTypeError 179 } 180 if *shadingType < 1 || *shadingType > 7 { 181 common.Log.Debug("Invalid shading type, not 1-7 (got %d)", *shadingType) 182 return nil, ErrTypeError 183 } 184 shading.ShadingType = shadingType 185 186 // Color space (required). 187 obj = dict.Get("ColorSpace") 188 if obj == nil { 189 common.Log.Debug("Required ColorSpace entry missing") 190 return nil, ErrRequiredAttributeMissing 191 } 192 cs, err := NewPdfColorspaceFromPdfObject(obj) 193 if err != nil { 194 common.Log.Debug("Failed loading colorspace: %v", err) 195 return nil, err 196 } 197 shading.ColorSpace = cs 198 199 // Background (optional). Array of color components. 200 obj = dict.Get("Background") 201 if obj != nil { 202 obj = TraceToDirectObject(obj) 203 arr, ok := obj.(*PdfObjectArray) 204 if !ok { 205 common.Log.Debug("Background should be specified by an array (got %T)", obj) 206 return nil, ErrTypeError 207 } 208 shading.Background = arr 209 } 210 211 // BBox. 212 obj = dict.Get("BBox") 213 if obj != nil { 214 obj = TraceToDirectObject(obj) 215 arr, ok := obj.(*PdfObjectArray) 216 if !ok { 217 common.Log.Debug("Background should be specified by an array (got %T)", obj) 218 return nil, ErrTypeError 219 } 220 rect, err := NewPdfRectangle(*arr) 221 if err != nil { 222 common.Log.Debug("BBox error: %v", err) 223 return nil, err 224 } 225 shading.BBox = rect 226 } 227 228 // AntiAlias. 229 obj = dict.Get("AntiAlias") 230 if obj != nil { 231 obj = TraceToDirectObject(obj) 232 val, ok := obj.(*PdfObjectBool) 233 if !ok { 234 common.Log.Debug("AntiAlias invalid type, should be bool (got %T)", obj) 235 return nil, ErrTypeError 236 } 237 shading.AntiAlias = val 238 } 239 240 // Load specific shading type specific entries. 241 switch *shadingType { 242 case 1: 243 ctx, err := newPdfShadingType1FromDictionary(dict) 244 if err != nil { 245 return nil, err 246 } 247 ctx.PdfShading = shading 248 shading.context = ctx 249 return shading, nil 250 case 2: 251 ctx, err := newPdfShadingType2FromDictionary(dict) 252 if err != nil { 253 return nil, err 254 } 255 ctx.PdfShading = shading 256 shading.context = ctx 257 return shading, nil 258 case 3: 259 ctx, err := newPdfShadingType3FromDictionary(dict) 260 if err != nil { 261 return nil, err 262 } 263 ctx.PdfShading = shading 264 shading.context = ctx 265 return shading, nil 266 case 4: 267 ctx, err := newPdfShadingType4FromDictionary(dict) 268 if err != nil { 269 return nil, err 270 } 271 ctx.PdfShading = shading 272 shading.context = ctx 273 return shading, nil 274 case 5: 275 ctx, err := newPdfShadingType5FromDictionary(dict) 276 if err != nil { 277 return nil, err 278 } 279 ctx.PdfShading = shading 280 shading.context = ctx 281 return shading, nil 282 case 6: 283 ctx, err := newPdfShadingType6FromDictionary(dict) 284 if err != nil { 285 return nil, err 286 } 287 ctx.PdfShading = shading 288 shading.context = ctx 289 return shading, nil 290 case 7: 291 ctx, err := newPdfShadingType7FromDictionary(dict) 292 if err != nil { 293 return nil, err 294 } 295 ctx.PdfShading = shading 296 shading.context = ctx 297 return shading, nil 298 } 299 300 return nil, errors.New("Unknown shading type") 301 } 302 303 // Load shading type 1 specific attributes from pdf object. Used in parsing/loading PDFs. 304 func newPdfShadingType1FromDictionary(dict *PdfObjectDictionary) (*PdfShadingType1, error) { 305 shading := PdfShadingType1{} 306 307 // Domain (optional). 308 if obj := dict.Get("Domain"); obj != nil { 309 obj = TraceToDirectObject(obj) 310 arr, ok := obj.(*PdfObjectArray) 311 if !ok { 312 common.Log.Debug("Domain not an array (got %T)", obj) 313 return nil, errors.New("Type check error") 314 } 315 shading.Domain = arr 316 } 317 318 // Matrix (optional). 319 if obj := dict.Get("Matrix"); obj != nil { 320 obj = TraceToDirectObject(obj) 321 arr, ok := obj.(*PdfObjectArray) 322 if !ok { 323 common.Log.Debug("Matrix not an array (got %T)", obj) 324 return nil, errors.New("Type check error") 325 } 326 shading.Matrix = arr 327 } 328 329 // Function (required). 330 obj := dict.Get("Function") 331 if obj == nil { 332 common.Log.Debug("Required attribute missing: Function") 333 return nil, ErrRequiredAttributeMissing 334 } 335 shading.Function = []PdfFunction{} 336 if array, is := obj.(*PdfObjectArray); is { 337 for _, obj := range *array { 338 function, err := newPdfFunctionFromPdfObject(obj) 339 if err != nil { 340 common.Log.Debug("Error parsing function: %v", err) 341 return nil, err 342 } 343 shading.Function = append(shading.Function, function) 344 } 345 } else { 346 function, err := newPdfFunctionFromPdfObject(obj) 347 if err != nil { 348 common.Log.Debug("Error parsing function: %v", err) 349 return nil, err 350 } 351 shading.Function = append(shading.Function, function) 352 } 353 354 return &shading, nil 355 } 356 357 // Load shading type 2 specific attributes from pdf object. Used in parsing/loading PDFs. 358 func newPdfShadingType2FromDictionary(dict *PdfObjectDictionary) (*PdfShadingType2, error) { 359 shading := PdfShadingType2{} 360 361 // Coords (required). 362 obj := dict.Get("Coords") 363 if obj == nil { 364 common.Log.Debug("Required attribute missing: Coords") 365 return nil, ErrRequiredAttributeMissing 366 } 367 arr, ok := obj.(*PdfObjectArray) 368 if !ok { 369 common.Log.Debug("Coords not an array (got %T)", obj) 370 return nil, errors.New("Type check error") 371 } 372 if len(*arr) != 4 { 373 common.Log.Debug("Coords length not 4 (got %d)", len(*arr)) 374 return nil, errors.New("Invalid attribute") 375 } 376 shading.Coords = arr 377 378 // Domain (optional). 379 if obj := dict.Get("Domain"); obj != nil { 380 obj = TraceToDirectObject(obj) 381 arr, ok := obj.(*PdfObjectArray) 382 if !ok { 383 common.Log.Debug("Domain not an array (got %T)", obj) 384 return nil, errors.New("Type check error") 385 } 386 shading.Domain = arr 387 } 388 389 // Function (required). 390 obj = dict.Get("Function") 391 if obj == nil { 392 common.Log.Debug("Required attribute missing: Function") 393 return nil, ErrRequiredAttributeMissing 394 } 395 shading.Function = []PdfFunction{} 396 if array, is := obj.(*PdfObjectArray); is { 397 for _, obj := range *array { 398 function, err := newPdfFunctionFromPdfObject(obj) 399 if err != nil { 400 common.Log.Debug("Error parsing function: %v", err) 401 return nil, err 402 } 403 shading.Function = append(shading.Function, function) 404 } 405 } else { 406 function, err := newPdfFunctionFromPdfObject(obj) 407 if err != nil { 408 common.Log.Debug("Error parsing function: %v", err) 409 return nil, err 410 } 411 shading.Function = append(shading.Function, function) 412 } 413 414 // Extend (optional). 415 if obj := dict.Get("Extend"); obj != nil { 416 obj = TraceToDirectObject(obj) 417 arr, ok := obj.(*PdfObjectArray) 418 if !ok { 419 common.Log.Debug("Matrix not an array (got %T)", obj) 420 return nil, ErrTypeCheck 421 } 422 if len(*arr) != 2 { 423 common.Log.Debug("Extend length not 2 (got %d)", len(*arr)) 424 return nil, ErrInvalidAttribute 425 } 426 shading.Extend = arr 427 } 428 429 return &shading, nil 430 } 431 432 // Load shading type 3 specific attributes from pdf object. Used in parsing/loading PDFs. 433 func newPdfShadingType3FromDictionary(dict *PdfObjectDictionary) (*PdfShadingType3, error) { 434 shading := PdfShadingType3{} 435 436 // Coords (required). 437 obj := dict.Get("Coords") 438 if obj == nil { 439 common.Log.Debug("Required attribute missing: Coords") 440 return nil, ErrRequiredAttributeMissing 441 } 442 arr, ok := obj.(*PdfObjectArray) 443 if !ok { 444 common.Log.Debug("Coords not an array (got %T)", obj) 445 return nil, ErrTypeError 446 } 447 if len(*arr) != 6 { 448 common.Log.Debug("Coords length not 6 (got %d)", len(*arr)) 449 return nil, ErrInvalidAttribute 450 } 451 shading.Coords = arr 452 453 // Domain (optional). 454 if obj := dict.Get("Domain"); obj != nil { 455 obj = TraceToDirectObject(obj) 456 arr, ok := obj.(*PdfObjectArray) 457 if !ok { 458 common.Log.Debug("Domain not an array (got %T)", obj) 459 return nil, ErrTypeError 460 } 461 shading.Domain = arr 462 } 463 464 // Function (required). 465 obj = dict.Get("Function") 466 if obj == nil { 467 common.Log.Debug("Required attribute missing: Function") 468 return nil, ErrRequiredAttributeMissing 469 } 470 shading.Function = []PdfFunction{} 471 if array, is := obj.(*PdfObjectArray); is { 472 for _, obj := range *array { 473 function, err := newPdfFunctionFromPdfObject(obj) 474 if err != nil { 475 common.Log.Debug("Error parsing function: %v", err) 476 return nil, err 477 } 478 shading.Function = append(shading.Function, function) 479 } 480 } else { 481 function, err := newPdfFunctionFromPdfObject(obj) 482 if err != nil { 483 common.Log.Debug("Error parsing function: %v", err) 484 return nil, err 485 } 486 shading.Function = append(shading.Function, function) 487 } 488 489 // Extend (optional). 490 if obj := dict.Get("Extend"); obj != nil { 491 obj = TraceToDirectObject(obj) 492 arr, ok := obj.(*PdfObjectArray) 493 if !ok { 494 common.Log.Debug("Matrix not an array (got %T)", obj) 495 return nil, ErrTypeError 496 } 497 if len(*arr) != 2 { 498 common.Log.Debug("Extend length not 2 (got %d)", len(*arr)) 499 return nil, ErrInvalidAttribute 500 } 501 shading.Extend = arr 502 } 503 504 return &shading, nil 505 } 506 507 // Load shading type 4 specific attributes from pdf object. Used in parsing/loading PDFs. 508 func newPdfShadingType4FromDictionary(dict *PdfObjectDictionary) (*PdfShadingType4, error) { 509 shading := PdfShadingType4{} 510 511 // BitsPerCoordinate (required). 512 obj := dict.Get("BitsPerCoordinate") 513 if obj == nil { 514 common.Log.Debug("Required attribute missing: BitsPerCoordinate") 515 return nil, ErrRequiredAttributeMissing 516 } 517 integer, ok := obj.(*PdfObjectInteger) 518 if !ok { 519 common.Log.Debug("BitsPerCoordinate not an integer (got %T)", obj) 520 return nil, ErrTypeError 521 } 522 shading.BitsPerCoordinate = integer 523 524 // BitsPerComponent (required). 525 obj = dict.Get("BitsPerComponent") 526 if obj == nil { 527 common.Log.Debug("Required attribute missing: BitsPerComponent") 528 return nil, ErrRequiredAttributeMissing 529 } 530 integer, ok = obj.(*PdfObjectInteger) 531 if !ok { 532 common.Log.Debug("BitsPerComponent not an integer (got %T)", obj) 533 return nil, ErrTypeError 534 } 535 shading.BitsPerComponent = integer 536 537 // BitsPerFlag (required). 538 obj = dict.Get("BitsPerFlag") 539 if obj == nil { 540 common.Log.Debug("Required attribute missing: BitsPerFlag") 541 return nil, ErrRequiredAttributeMissing 542 } 543 integer, ok = obj.(*PdfObjectInteger) 544 if !ok { 545 common.Log.Debug("BitsPerFlag not an integer (got %T)", obj) 546 return nil, ErrTypeError 547 } 548 shading.BitsPerComponent = integer 549 550 // Decode (required). 551 obj = dict.Get("Decode") 552 if obj == nil { 553 common.Log.Debug("Required attribute missing: Decode") 554 return nil, ErrRequiredAttributeMissing 555 } 556 arr, ok := obj.(*PdfObjectArray) 557 if !ok { 558 common.Log.Debug("Decode not an array (got %T)", obj) 559 return nil, ErrTypeError 560 } 561 shading.Decode = arr 562 563 // Function (required). 564 obj = dict.Get("Function") 565 if obj == nil { 566 common.Log.Debug("Required attribute missing: Function") 567 return nil, ErrRequiredAttributeMissing 568 } 569 shading.Function = []PdfFunction{} 570 if array, is := obj.(*PdfObjectArray); is { 571 for _, obj := range *array { 572 function, err := newPdfFunctionFromPdfObject(obj) 573 if err != nil { 574 common.Log.Debug("Error parsing function: %v", err) 575 return nil, err 576 } 577 shading.Function = append(shading.Function, function) 578 } 579 } else { 580 function, err := newPdfFunctionFromPdfObject(obj) 581 if err != nil { 582 common.Log.Debug("Error parsing function: %v", err) 583 return nil, err 584 } 585 shading.Function = append(shading.Function, function) 586 } 587 588 return &shading, nil 589 } 590 591 // Load shading type 5 specific attributes from pdf object. Used in parsing/loading PDFs. 592 func newPdfShadingType5FromDictionary(dict *PdfObjectDictionary) (*PdfShadingType5, error) { 593 shading := PdfShadingType5{} 594 595 // BitsPerCoordinate (required). 596 obj := dict.Get("BitsPerCoordinate") 597 if obj == nil { 598 common.Log.Debug("Required attribute missing: BitsPerCoordinate") 599 return nil, ErrRequiredAttributeMissing 600 } 601 integer, ok := obj.(*PdfObjectInteger) 602 if !ok { 603 common.Log.Debug("BitsPerCoordinate not an integer (got %T)", obj) 604 return nil, ErrTypeError 605 } 606 shading.BitsPerCoordinate = integer 607 608 // BitsPerComponent (required). 609 obj = dict.Get("BitsPerComponent") 610 if obj == nil { 611 common.Log.Debug("Required attribute missing: BitsPerComponent") 612 return nil, ErrRequiredAttributeMissing 613 } 614 integer, ok = obj.(*PdfObjectInteger) 615 if !ok { 616 common.Log.Debug("BitsPerComponent not an integer (got %T)", obj) 617 return nil, ErrTypeError 618 } 619 shading.BitsPerComponent = integer 620 621 // VerticesPerRow (required). 622 obj = dict.Get("VerticesPerRow") 623 if obj == nil { 624 common.Log.Debug("Required attribute missing: VerticesPerRow") 625 return nil, ErrRequiredAttributeMissing 626 } 627 integer, ok = obj.(*PdfObjectInteger) 628 if !ok { 629 common.Log.Debug("VerticesPerRow not an integer (got %T)", obj) 630 return nil, ErrTypeError 631 } 632 shading.VerticesPerRow = integer 633 634 // Decode (required). 635 obj = dict.Get("Decode") 636 if obj == nil { 637 common.Log.Debug("Required attribute missing: Decode") 638 return nil, ErrRequiredAttributeMissing 639 } 640 arr, ok := obj.(*PdfObjectArray) 641 if !ok { 642 common.Log.Debug("Decode not an array (got %T)", obj) 643 return nil, ErrTypeError 644 } 645 shading.Decode = arr 646 647 // Function (optional). 648 if obj := dict.Get("Function"); obj != nil { 649 // Function (required). 650 shading.Function = []PdfFunction{} 651 if array, is := obj.(*PdfObjectArray); is { 652 for _, obj := range *array { 653 function, err := newPdfFunctionFromPdfObject(obj) 654 if err != nil { 655 common.Log.Debug("Error parsing function: %v", err) 656 return nil, err 657 } 658 shading.Function = append(shading.Function, function) 659 } 660 } else { 661 function, err := newPdfFunctionFromPdfObject(obj) 662 if err != nil { 663 common.Log.Debug("Error parsing function: %v", err) 664 return nil, err 665 } 666 shading.Function = append(shading.Function, function) 667 } 668 } 669 670 return &shading, nil 671 } 672 673 // Load shading type 6 specific attributes from pdf object. Used in parsing/loading PDFs. 674 func newPdfShadingType6FromDictionary(dict *PdfObjectDictionary) (*PdfShadingType6, error) { 675 shading := PdfShadingType6{} 676 677 // BitsPerCoordinate (required). 678 obj := dict.Get("BitsPerCoordinate") 679 if obj == nil { 680 common.Log.Debug("Required attribute missing: BitsPerCoordinate") 681 return nil, ErrRequiredAttributeMissing 682 } 683 integer, ok := obj.(*PdfObjectInteger) 684 if !ok { 685 common.Log.Debug("BitsPerCoordinate not an integer (got %T)", obj) 686 return nil, ErrTypeError 687 } 688 shading.BitsPerCoordinate = integer 689 690 // BitsPerComponent (required). 691 obj = dict.Get("BitsPerComponent") 692 if obj == nil { 693 common.Log.Debug("Required attribute missing: BitsPerComponent") 694 return nil, ErrRequiredAttributeMissing 695 } 696 integer, ok = obj.(*PdfObjectInteger) 697 if !ok { 698 common.Log.Debug("BitsPerComponent not an integer (got %T)", obj) 699 return nil, ErrTypeError 700 } 701 shading.BitsPerComponent = integer 702 703 // BitsPerFlag (required). 704 obj = dict.Get("BitsPerFlag") 705 if obj == nil { 706 common.Log.Debug("Required attribute missing: BitsPerFlag") 707 return nil, ErrRequiredAttributeMissing 708 } 709 integer, ok = obj.(*PdfObjectInteger) 710 if !ok { 711 common.Log.Debug("BitsPerFlag not an integer (got %T)", obj) 712 return nil, ErrTypeError 713 } 714 shading.BitsPerComponent = integer 715 716 // Decode (required). 717 obj = dict.Get("Decode") 718 if obj == nil { 719 common.Log.Debug("Required attribute missing: Decode") 720 return nil, ErrRequiredAttributeMissing 721 } 722 arr, ok := obj.(*PdfObjectArray) 723 if !ok { 724 common.Log.Debug("Decode not an array (got %T)", obj) 725 return nil, ErrTypeError 726 } 727 shading.Decode = arr 728 729 // Function (optional). 730 if obj := dict.Get("Function"); obj != nil { 731 shading.Function = []PdfFunction{} 732 if array, is := obj.(*PdfObjectArray); is { 733 for _, obj := range *array { 734 function, err := newPdfFunctionFromPdfObject(obj) 735 if err != nil { 736 common.Log.Debug("Error parsing function: %v", err) 737 return nil, err 738 } 739 shading.Function = append(shading.Function, function) 740 } 741 } else { 742 function, err := newPdfFunctionFromPdfObject(obj) 743 if err != nil { 744 common.Log.Debug("Error parsing function: %v", err) 745 return nil, err 746 } 747 shading.Function = append(shading.Function, function) 748 } 749 } 750 751 return &shading, nil 752 } 753 754 // Load shading type 7 specific attributes from pdf object. Used in parsing/loading PDFs. 755 func newPdfShadingType7FromDictionary(dict *PdfObjectDictionary) (*PdfShadingType7, error) { 756 shading := PdfShadingType7{} 757 758 // BitsPerCoordinate (required). 759 obj := dict.Get("BitsPerCoordinate") 760 if obj == nil { 761 common.Log.Debug("Required attribute missing: BitsPerCoordinate") 762 return nil, ErrRequiredAttributeMissing 763 } 764 integer, ok := obj.(*PdfObjectInteger) 765 if !ok { 766 common.Log.Debug("BitsPerCoordinate not an integer (got %T)", obj) 767 return nil, ErrTypeError 768 } 769 shading.BitsPerCoordinate = integer 770 771 // BitsPerComponent (required). 772 obj = dict.Get("BitsPerComponent") 773 if obj == nil { 774 common.Log.Debug("Required attribute missing: BitsPerComponent") 775 return nil, ErrRequiredAttributeMissing 776 } 777 integer, ok = obj.(*PdfObjectInteger) 778 if !ok { 779 common.Log.Debug("BitsPerComponent not an integer (got %T)", obj) 780 return nil, ErrTypeError 781 } 782 shading.BitsPerComponent = integer 783 784 // BitsPerFlag (required). 785 obj = dict.Get("BitsPerFlag") 786 if obj == nil { 787 common.Log.Debug("Required attribute missing: BitsPerFlag") 788 return nil, ErrRequiredAttributeMissing 789 } 790 integer, ok = obj.(*PdfObjectInteger) 791 if !ok { 792 common.Log.Debug("BitsPerFlag not an integer (got %T)", obj) 793 return nil, ErrTypeError 794 } 795 shading.BitsPerComponent = integer 796 797 // Decode (required). 798 obj = dict.Get("Decode") 799 if obj == nil { 800 common.Log.Debug("Required attribute missing: Decode") 801 return nil, ErrRequiredAttributeMissing 802 } 803 arr, ok := obj.(*PdfObjectArray) 804 if !ok { 805 common.Log.Debug("Decode not an array (got %T)", obj) 806 return nil, ErrTypeError 807 } 808 shading.Decode = arr 809 810 // Function (optional). 811 if obj := dict.Get("Function"); obj != nil { 812 shading.Function = []PdfFunction{} 813 if array, is := obj.(*PdfObjectArray); is { 814 for _, obj := range *array { 815 function, err := newPdfFunctionFromPdfObject(obj) 816 if err != nil { 817 common.Log.Debug("Error parsing function: %v", err) 818 return nil, err 819 } 820 shading.Function = append(shading.Function, function) 821 } 822 } else { 823 function, err := newPdfFunctionFromPdfObject(obj) 824 if err != nil { 825 common.Log.Debug("Error parsing function: %v", err) 826 return nil, err 827 } 828 shading.Function = append(shading.Function, function) 829 } 830 } 831 832 return &shading, nil 833 } 834 835 /* Conversion to pdf objects. */ 836 837 func (this *PdfShading) ToPdfObject() PdfObject { 838 container := this.container 839 840 d, err := this.getShadingDict() 841 if err != nil { 842 common.Log.Error("Unable to access shading dict") 843 return nil 844 } 845 846 if this.ShadingType != nil { 847 d.Set("ShadingType", this.ShadingType) 848 } 849 if this.ColorSpace != nil { 850 d.Set("ColorSpace", this.ColorSpace.ToPdfObject()) 851 } 852 if this.Background != nil { 853 d.Set("Background", this.Background) 854 } 855 if this.BBox != nil { 856 d.Set("BBox", this.BBox.ToPdfObject()) 857 } 858 if this.AntiAlias != nil { 859 d.Set("AntiAlias", this.AntiAlias) 860 } 861 862 return container 863 } 864 865 func (this *PdfShadingType1) ToPdfObject() PdfObject { 866 this.PdfShading.ToPdfObject() 867 868 d, err := this.getShadingDict() 869 if err != nil { 870 common.Log.Error("Unable to access shading dict") 871 return nil 872 } 873 874 if this.Domain != nil { 875 d.Set("Domain", this.Domain) 876 } 877 if this.Matrix != nil { 878 d.Set("Matrix", this.Matrix) 879 } 880 if this.Function != nil { 881 if len(this.Function) == 1 { 882 d.Set("Function", this.Function[0].ToPdfObject()) 883 } else { 884 farr := MakeArray() 885 for _, f := range this.Function { 886 farr.Append(f.ToPdfObject()) 887 } 888 d.Set("Function", farr) 889 } 890 } 891 892 return this.container 893 } 894 895 func (this *PdfShadingType2) ToPdfObject() PdfObject { 896 this.PdfShading.ToPdfObject() 897 898 d, err := this.getShadingDict() 899 if err != nil { 900 common.Log.Error("Unable to access shading dict") 901 return nil 902 } 903 if d == nil { 904 common.Log.Error("Shading dict is nil") 905 return nil 906 } 907 if this.Coords != nil { 908 d.Set("Coords", this.Coords) 909 } 910 if this.Domain != nil { 911 d.Set("Domain", this.Domain) 912 } 913 if this.Function != nil { 914 if len(this.Function) == 1 { 915 d.Set("Function", this.Function[0].ToPdfObject()) 916 } else { 917 farr := MakeArray() 918 for _, f := range this.Function { 919 farr.Append(f.ToPdfObject()) 920 } 921 d.Set("Function", farr) 922 } 923 } 924 if this.Extend != nil { 925 d.Set("Extend", this.Extend) 926 } 927 928 return this.container 929 } 930 931 func (this *PdfShadingType3) ToPdfObject() PdfObject { 932 this.PdfShading.ToPdfObject() 933 934 d, err := this.getShadingDict() 935 if err != nil { 936 common.Log.Error("Unable to access shading dict") 937 return nil 938 } 939 940 if this.Coords != nil { 941 d.Set("Coords", this.Coords) 942 } 943 if this.Domain != nil { 944 d.Set("Domain", this.Domain) 945 } 946 if this.Function != nil { 947 if len(this.Function) == 1 { 948 d.Set("Function", this.Function[0].ToPdfObject()) 949 } else { 950 farr := MakeArray() 951 for _, f := range this.Function { 952 farr.Append(f.ToPdfObject()) 953 } 954 d.Set("Function", farr) 955 } 956 } 957 if this.Extend != nil { 958 d.Set("Extend", this.Extend) 959 } 960 961 return this.container 962 } 963 964 func (this *PdfShadingType4) ToPdfObject() PdfObject { 965 this.PdfShading.ToPdfObject() 966 967 d, err := this.getShadingDict() 968 if err != nil { 969 common.Log.Error("Unable to access shading dict") 970 return nil 971 } 972 973 if this.BitsPerCoordinate != nil { 974 d.Set("BitsPerCoordinate", this.BitsPerCoordinate) 975 } 976 if this.BitsPerComponent != nil { 977 d.Set("BitsPerComponent", this.BitsPerComponent) 978 } 979 if this.BitsPerFlag != nil { 980 d.Set("BitsPerFlag", this.BitsPerFlag) 981 } 982 if this.Decode != nil { 983 d.Set("Decode", this.Decode) 984 } 985 if this.Function != nil { 986 if len(this.Function) == 1 { 987 d.Set("Function", this.Function[0].ToPdfObject()) 988 } else { 989 farr := MakeArray() 990 for _, f := range this.Function { 991 farr.Append(f.ToPdfObject()) 992 } 993 d.Set("Function", farr) 994 } 995 } 996 997 return this.container 998 } 999 1000 func (this *PdfShadingType5) ToPdfObject() PdfObject { 1001 this.PdfShading.ToPdfObject() 1002 1003 d, err := this.getShadingDict() 1004 if err != nil { 1005 common.Log.Error("Unable to access shading dict") 1006 return nil 1007 } 1008 1009 if this.BitsPerCoordinate != nil { 1010 d.Set("BitsPerCoordinate", this.BitsPerCoordinate) 1011 } 1012 if this.BitsPerComponent != nil { 1013 d.Set("BitsPerComponent", this.BitsPerComponent) 1014 } 1015 if this.VerticesPerRow != nil { 1016 d.Set("VerticesPerRow", this.VerticesPerRow) 1017 } 1018 if this.Decode != nil { 1019 d.Set("Decode", this.Decode) 1020 } 1021 if this.Function != nil { 1022 if len(this.Function) == 1 { 1023 d.Set("Function", this.Function[0].ToPdfObject()) 1024 } else { 1025 farr := MakeArray() 1026 for _, f := range this.Function { 1027 farr.Append(f.ToPdfObject()) 1028 } 1029 d.Set("Function", farr) 1030 } 1031 } 1032 1033 return this.container 1034 } 1035 1036 func (this *PdfShadingType6) ToPdfObject() PdfObject { 1037 this.PdfShading.ToPdfObject() 1038 1039 d, err := this.getShadingDict() 1040 if err != nil { 1041 common.Log.Error("Unable to access shading dict") 1042 return nil 1043 } 1044 1045 if this.BitsPerCoordinate != nil { 1046 d.Set("BitsPerCoordinate", this.BitsPerCoordinate) 1047 } 1048 if this.BitsPerComponent != nil { 1049 d.Set("BitsPerComponent", this.BitsPerComponent) 1050 } 1051 if this.BitsPerFlag != nil { 1052 d.Set("BitsPerFlag", this.BitsPerFlag) 1053 } 1054 if this.Decode != nil { 1055 d.Set("Decode", this.Decode) 1056 } 1057 if this.Function != nil { 1058 if len(this.Function) == 1 { 1059 d.Set("Function", this.Function[0].ToPdfObject()) 1060 } else { 1061 farr := MakeArray() 1062 for _, f := range this.Function { 1063 farr.Append(f.ToPdfObject()) 1064 } 1065 d.Set("Function", farr) 1066 } 1067 } 1068 1069 return this.container 1070 } 1071 1072 func (this *PdfShadingType7) ToPdfObject() PdfObject { 1073 this.PdfShading.ToPdfObject() 1074 1075 d, err := this.getShadingDict() 1076 if err != nil { 1077 common.Log.Error("Unable to access shading dict") 1078 return nil 1079 } 1080 1081 if this.BitsPerCoordinate != nil { 1082 d.Set("BitsPerCoordinate", this.BitsPerCoordinate) 1083 } 1084 if this.BitsPerComponent != nil { 1085 d.Set("BitsPerComponent", this.BitsPerComponent) 1086 } 1087 if this.BitsPerFlag != nil { 1088 d.Set("BitsPerFlag", this.BitsPerFlag) 1089 } 1090 if this.Decode != nil { 1091 d.Set("Decode", this.Decode) 1092 } 1093 if this.Function != nil { 1094 if len(this.Function) == 1 { 1095 d.Set("Function", this.Function[0].ToPdfObject()) 1096 } else { 1097 farr := MakeArray() 1098 for _, f := range this.Function { 1099 farr.Append(f.ToPdfObject()) 1100 } 1101 d.Set("Function", farr) 1102 } 1103 } 1104 1105 return this.container 1106 }