File indexing completed on 2024-05-19 04:27:29

0001 /*
0002  *  SPDX-FileCopyrightText: 2009 Boudewijn Rempt <boud@valdyas.org>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 #ifndef PSD_RESOURCE_BLOCK_H
0007 #define PSD_RESOURCE_BLOCK_H
0008 
0009 #include "kritapsd_export.h"
0010 
0011 class QIODevice;
0012 
0013 #include <QBuffer>
0014 #include <QString>
0015 #include <kis_debug.h>
0016 #include <klocalizedstring.h>
0017 
0018 #include <kis_annotation.h>
0019 
0020 #include "psd.h"
0021 #include "psd_resource_section.h"
0022 #include "psd_utils.h"
0023 
0024 /**
0025  * @brief The PSDResourceInterpreter struct interprets the data in a psd resource block
0026  */
0027 class KRITAPSD_EXPORT PSDInterpretedResource
0028 {
0029 public:
0030     virtual ~PSDInterpretedResource()
0031     {
0032     }
0033 
0034     virtual bool interpretBlock(QByteArray /*data*/)
0035     {
0036         return true;
0037     }
0038     virtual bool createBlock(QByteArray & /*data*/)
0039     {
0040         return true;
0041     }
0042     virtual bool valid()
0043     {
0044         return true;
0045     }
0046 
0047     virtual QString displayText()
0048     {
0049         return QString();
0050     }
0051 
0052     QString error;
0053 
0054 protected:
0055     void startBlock(QBuffer &buf, PSDImageResourceSection::PSDResourceID id, quint32 size)
0056     {
0057         if (!buf.isOpen()) {
0058             buf.open(QBuffer::WriteOnly);
0059         }
0060         buf.write("8BIM", 4);
0061         psdwrite(buf, (quint16)id);
0062         psdwrite(buf, (quint16)0); // We simply never save out the name, for now
0063         psdwrite(buf, (quint32)size);
0064     }
0065 };
0066 
0067 /**
0068  * Contains the unparsed contents of the image resource blocks
0069  */
0070 class KRITAPSD_EXPORT PSDResourceBlock : public KisAnnotation
0071 {
0072 public:
0073     PSDResourceBlock();
0074 
0075     ~PSDResourceBlock() override
0076     {
0077         delete resource;
0078     }
0079 
0080     KisAnnotation *clone() const Q_DECL_OVERRIDE
0081     {
0082         // HACK ALERT: we are evil! use normal copying instead!
0083         PSDResourceBlock *copied = new PSDResourceBlock();
0084 
0085         QBuffer buffer;
0086         buffer.open(QBuffer::WriteOnly);
0087 
0088         if (!write(buffer)) {
0089             qWarning() << "Could not copy PSDResourceBlock" << error;
0090             delete copied;
0091             return 0;
0092         }
0093         buffer.close();
0094         buffer.open(QBuffer::ReadOnly);
0095 
0096         if (!copied->read(buffer)) {
0097             qWarning() << "Could not copy PSDResourceBlock" << copied->error;
0098             delete copied;
0099             return 0;
0100         }
0101 
0102         return copied;
0103     }
0104 
0105     QString displayText() const override
0106     {
0107         if (resource) {
0108             return resource->displayText();
0109         }
0110         return i18n("Unparsed Resource Block");
0111     }
0112 
0113     bool read(QIODevice &io);
0114     bool write(QIODevice &io) const;
0115     bool valid();
0116 
0117     quint16 identifier;
0118     QString name;
0119     quint32 dataSize;
0120     QByteArray data;
0121 
0122     PSDInterpretedResource *resource;
0123 
0124     mutable QString error;
0125 };
0126 
0127 /* 0x03e9 - Optional - Mac print manager print info record */
0128 struct KRITAPSD_EXPORT MAC_PRINT_INFO_1001 : public PSDInterpretedResource {
0129     bool interpretBlock(QByteArray /*data*/) override
0130     {
0131         dbgFile << "Reading MAC_PRINT_INFO_1001";
0132         return true;
0133     }
0134 };
0135 
0136 /* 0x03ed - ResolutionInfo structure */
0137 struct KRITAPSD_EXPORT RESN_INFO_1005 : public PSDInterpretedResource {
0138     // XXX: Krita only uses INCH internally
0139     enum PSDUnit {
0140         PSD_UNIT_INCH = 1, /* inches */
0141         PSD_UNIT_CM = 2, /* cm */
0142         PSD_UNIT_POINT = 3, /* points  (72 points =   1 inch) */
0143         PSD_UNIT_PICA = 4, /* pica    ( 6 pica   =   1 inch) */
0144         PSD_UNIT_COLUMN = 5 /* columns ( column defined in ps prefs, default = 2.5 inches) */
0145     };
0146 
0147     RESN_INFO_1005()
0148         : hRes(300)
0149         , hResUnit(PSD_UNIT_INCH)
0150         , widthUnit(PSD_UNIT_INCH)
0151         , vRes(300)
0152         , vResUnit(PSD_UNIT_INCH)
0153         , heightUnit(PSD_UNIT_INCH)
0154     {
0155     }
0156 
0157     bool interpretBlock(QByteArray data) override;
0158     bool createBlock(QByteArray &data) override;
0159 
0160     Fixed hRes;
0161     quint16 hResUnit;
0162     quint16 widthUnit;
0163     Fixed vRes;
0164     quint16 vResUnit;
0165     quint16 heightUnit;
0166 };
0167 
0168 /* 0x03ee - Alpha channel names */
0169 struct KRITAPSD_EXPORT ALPHA_NAMES_1006 : public PSDInterpretedResource {
0170     bool interpretBlock(QByteArray /*data*/) override
0171     {
0172         dbgFile << "Reading ALPHA_NAMES_1006";
0173 
0174         return true;
0175     }
0176 };
0177 
0178 /* 0x03ef - DisplayInfo structure */
0179 struct KRITAPSD_EXPORT DISPLAY_INFO_1007 : public PSDInterpretedResource {
0180     bool interpretBlock(QByteArray /*data*/) override
0181     {
0182         dbgFile << "Reading DISPLAY_INFO_1007";
0183         return true;
0184     }
0185 };
0186 
0187 /* 0x03f0 - Optional - Caption string */
0188 struct KRITAPSD_EXPORT CAPTION_1008 : public PSDInterpretedResource {
0189     bool interpretBlock(QByteArray /*data*/) override
0190     {
0191         dbgFile << "Reading CAPTION_1008";
0192         return true;
0193     }
0194 };
0195 
0196 /* 0x03f1 - Border info */
0197 struct KRITAPSD_EXPORT BORDER_INFO_1009 : public PSDInterpretedResource {
0198     bool interpretBlock(QByteArray /*data*/) override
0199     {
0200         dbgFile << "Reading BORDER_INFO_1009";
0201         return true;
0202     }
0203 };
0204 
0205 /* 0x03f2 - Background color */
0206 struct KRITAPSD_EXPORT BACKGROUND_COL_1010 : public PSDInterpretedResource {
0207     bool interpretBlock(QByteArray /*data*/) override
0208     {
0209         dbgFile << "Reading BACKGROUND_COL_1010";
0210         return true;
0211     }
0212 };
0213 
0214 /* 0x03f3 - Print flags */
0215 struct KRITAPSD_EXPORT PRINT_FLAGS_1011 : public PSDInterpretedResource {
0216     bool interpretBlock(QByteArray /*data*/) override
0217     {
0218         dbgFile << "Reading PRINT_FLAGS_1011";
0219         return true;
0220     }
0221 };
0222 
0223 /* 0x03f4 - Greyscale and multichannel halftoning info */
0224 struct KRITAPSD_EXPORT GREY_HALFTONE_1012 : public PSDInterpretedResource {
0225     bool interpretBlock(QByteArray /*data*/) override
0226     {
0227         dbgFile << "Reading GREY_HALFTONE_1012";
0228         return true;
0229     }
0230 };
0231 
0232 /* 0x03f5 - Color halftoning info */
0233 struct KRITAPSD_EXPORT COLOR_HALFTONE_1013 : public PSDInterpretedResource {
0234     bool interpretBlock(QByteArray /*data*/) override
0235     {
0236         dbgFile << "Reading COLOR_HALFTONE_1013";
0237         return true;
0238     }
0239 };
0240 
0241 /* 0x03f6 - Duotone halftoning info */
0242 struct KRITAPSD_EXPORT DUOTONE_HALFTONE_1014 : public PSDInterpretedResource {
0243     bool interpretBlock(QByteArray /*data*/) override
0244     {
0245         dbgFile << "Reading DUOTONE_HALFTONE_1014";
0246         return true;
0247     }
0248 };
0249 
0250 /* 0x03f7 - Greyscale and multichannel transfer functions */
0251 struct KRITAPSD_EXPORT GREY_XFER_1015 : public PSDInterpretedResource {
0252     bool interpretBlock(QByteArray /*data*/) override
0253     {
0254         dbgFile << "Reading GREY_XFER_1015";
0255         return true;
0256     }
0257 };
0258 
0259 /* 0x03f8 - Color transfer functions */
0260 struct KRITAPSD_EXPORT COLOR_XFER_1016 : public PSDInterpretedResource {
0261     bool interpretBlock(QByteArray /*data*/) override
0262     {
0263         dbgFile << "Reading COLOR_XFER_1016";
0264         return true;
0265     }
0266 };
0267 
0268 /* 0x03f9 - Duotone transfer functions */
0269 struct KRITAPSD_EXPORT DUOTONE_XFER_1017 : public PSDInterpretedResource {
0270     bool interpretBlock(QByteArray /*data*/) override
0271     {
0272         dbgFile << "Reading DUOTONE_XFER_1017";
0273         return true;
0274     }
0275 };
0276 
0277 /* 0x03fa - Duotone image information */
0278 struct KRITAPSD_EXPORT DUOTONE_INFO_1018 : public PSDInterpretedResource {
0279     bool interpretBlock(QByteArray /*data*/) override
0280     {
0281         dbgFile << "Reading DUOTONE_INFO_1018";
0282         return true;
0283     }
0284 };
0285 
0286 /* 0x03fb - Effective black & white values for dot range */
0287 struct KRITAPSD_EXPORT EFFECTIVE_BW_1019 : public PSDInterpretedResource {
0288     bool interpretBlock(QByteArray /*data*/) override
0289     {
0290         dbgFile << "Reading EFFECTIVE_BW_1019";
0291         return true;
0292     }
0293 };
0294 
0295 /* 0x03fd - EPS options */
0296 struct KRITAPSD_EXPORT EPS_OPT_1021 : public PSDInterpretedResource {
0297     bool interpretBlock(QByteArray /*data*/) override
0298     {
0299         dbgFile << "Reading EPS_OPT_1021";
0300         return true;
0301     }
0302 };
0303 
0304 /* 0x03fe - Quick mask info */
0305 struct KRITAPSD_EXPORT QUICK_MASK_1022 : public PSDInterpretedResource {
0306     bool interpretBlock(QByteArray /*data*/) override
0307     {
0308         dbgFile << "Reading QUICK_MASK_1022";
0309         return true;
0310     }
0311 };
0312 
0313 /* 0x0400 - Layer state info */
0314 struct KRITAPSD_EXPORT LAYER_STATE_1024 : public PSDInterpretedResource {
0315     bool interpretBlock(QByteArray /*data*/) override
0316     {
0317         dbgFile << "Reading LAYER_STATE_1024";
0318         return true;
0319     }
0320 };
0321 
0322 /* 0x0401 - Working path (not saved) */
0323 struct KRITAPSD_EXPORT WORKING_PATH_1025 : public PSDInterpretedResource {
0324     bool interpretBlock(QByteArray /*data*/) override
0325     {
0326         dbgFile << "Reading WORKING_PATH_1025";
0327         return true;
0328     }
0329 };
0330 
0331 /* 0x0402 - Layers group info */
0332 struct KRITAPSD_EXPORT LAYER_GROUP_1026 : public PSDInterpretedResource {
0333     bool interpretBlock(QByteArray /*data*/) override
0334     {
0335         dbgFile << "Reading LAYER_GROUP_1026";
0336         return true;
0337     }
0338 };
0339 
0340 /* 0x0404 - IPTC-NAA record (IMV4.pdf) */
0341 struct KRITAPSD_EXPORT IPTC_NAA_DATA_1028 : public PSDInterpretedResource {
0342     bool interpretBlock(QByteArray /*data*/) override
0343     {
0344         dbgFile << "Reading IPTC_NAA_DATA_1028";
0345         return true;
0346     }
0347 };
0348 
0349 /* 0x0405 - Image mode for raw format files */
0350 struct KRITAPSD_EXPORT IMAGE_MODE_RAW_1029 : public PSDInterpretedResource {
0351     bool interpretBlock(QByteArray /*data*/) override
0352     {
0353         dbgFile << "Reading IMAGE_MODE_RAW_1029";
0354         return true;
0355     }
0356 };
0357 
0358 /* 0x0406 - JPEG quality */
0359 struct KRITAPSD_EXPORT JPEG_QUAL_1030 : public PSDInterpretedResource {
0360     bool interpretBlock(QByteArray /*data*/) override
0361     {
0362         dbgFile << "Reading JPEG_QUAL_1030";
0363         return true;
0364     }
0365 };
0366 
0367 /* 0x0408 - Grid & guide info */
0368 struct KRITAPSD_EXPORT GRID_GUIDE_1032 : public PSDInterpretedResource {
0369     bool interpretBlock(QByteArray /*data*/) override
0370     {
0371         dbgFile << "Reading GRID_GUIDE_1032";
0372         return true;
0373     }
0374 };
0375 
0376 /* 0x0409 - Thumbnail resource */
0377 struct KRITAPSD_EXPORT THUMB_RES_1033 : public PSDInterpretedResource {
0378     bool interpretBlock(QByteArray /*data*/) override
0379     {
0380         dbgFile << "Reading THUMB_RES_1033";
0381         return true;
0382     }
0383 };
0384 
0385 /* 0x040a - Copyright flag */
0386 struct KRITAPSD_EXPORT COPYRIGHT_FLG_1034 : public PSDInterpretedResource {
0387     bool interpretBlock(QByteArray /*data*/) override
0388     {
0389         dbgFile << "Reading COPYRIGHT_FLG_1034";
0390         return true;
0391     }
0392 };
0393 
0394 /* 0x040b - URL string */
0395 struct KRITAPSD_EXPORT URL_1035 : public PSDInterpretedResource {
0396     bool interpretBlock(QByteArray /*data*/) override
0397     {
0398         dbgFile << "Reading URL_1035";
0399         return true;
0400     }
0401 };
0402 
0403 /* 0x040c - Thumbnail resource */
0404 struct KRITAPSD_EXPORT THUMB_RES2_1036 : public PSDInterpretedResource {
0405     bool interpretBlock(QByteArray /*data*/) override
0406     {
0407         dbgFile << "Reading THUMB_RES2_1036";
0408         return true;
0409     }
0410 };
0411 
0412 /* 0x040d - Global angle */
0413 struct KRITAPSD_EXPORT GLOBAL_ANGLE_1037 : public PSDInterpretedResource {
0414     GLOBAL_ANGLE_1037()
0415         : angle(30)
0416     {
0417     }
0418 
0419     bool interpretBlock(QByteArray data) override
0420     {
0421         dbgFile << "Reading GLOBAL_ANGLE_1037";
0422 
0423         QDataStream ds(data);
0424         ds.setByteOrder(QDataStream::BigEndian);
0425 
0426         ds >> angle;
0427 
0428         return true;
0429     }
0430 
0431     bool createBlock(QByteArray &data) override
0432     {
0433         QBuffer buf(&data);
0434         startBlock(buf, PSDImageResourceSection::GLOBAL_ANGLE, 4);
0435         psdwrite(buf, (quint32)angle);
0436         return true;
0437     }
0438 
0439     bool valid() override
0440     {
0441         return true;
0442     }
0443 
0444     QString displayText() override
0445     {
0446         return QString("Global Angle: %1").arg(angle);
0447     }
0448 
0449     qint32 angle;
0450 };
0451 
0452 /* 0x040e - Color samplers resource */
0453 struct KRITAPSD_EXPORT COLOR_SAMPLER_1038 : public PSDInterpretedResource {
0454     bool interpretBlock(QByteArray /*data*/) override
0455     {
0456         dbgFile << "Reading COLOR_SAMPLER_1038";
0457         return true;
0458     }
0459 };
0460 
0461 /* 0x040f - ICC Profile */
0462 struct KRITAPSD_EXPORT ICC_PROFILE_1039 : public PSDInterpretedResource {
0463     bool interpretBlock(QByteArray data) override;
0464     bool createBlock(QByteArray &data) override;
0465 
0466     QByteArray icc;
0467 };
0468 
0469 /* 0x0410 - Watermark */
0470 struct KRITAPSD_EXPORT WATERMARK_1040 : public PSDInterpretedResource {
0471     bool interpretBlock(QByteArray /*data*/) override
0472     {
0473         dbgFile << "Reading WATERMARK_1040";
0474         return true;
0475     }
0476 };
0477 
0478 /* 0x0411 - Do not use ICC profile flag */
0479 struct KRITAPSD_EXPORT ICC_UNTAGGED_1041 : public PSDInterpretedResource {
0480     bool interpretBlock(QByteArray /*data*/) override
0481     {
0482         dbgFile << "Reading ICC_UNTAGGED_1041";
0483         return true;
0484     }
0485 };
0486 
0487 /* 0x0412 - Show / hide all effects layers */
0488 struct KRITAPSD_EXPORT EFFECTS_VISIBLE_1042 : public PSDInterpretedResource {
0489     bool interpretBlock(QByteArray /*data*/) override
0490     {
0491         dbgFile << "Reading EFFECTS_VISIBLE_1042";
0492         return true;
0493     }
0494 };
0495 
0496 /* 0x0413 - Spot halftone */
0497 struct KRITAPSD_EXPORT SPOT_HALFTONE_1043 : public PSDInterpretedResource {
0498     bool interpretBlock(QByteArray /*data*/) override
0499     {
0500         dbgFile << "Reading SPOT_HALFTONE_1043";
0501         return true;
0502     }
0503 };
0504 
0505 /* 0x0414 - Document specific IDs */
0506 struct KRITAPSD_EXPORT DOC_IDS_1044 : public PSDInterpretedResource {
0507     bool interpretBlock(QByteArray /*data*/) override
0508     {
0509         dbgFile << "Reading DOC_IDS_1044";
0510         return true;
0511     }
0512 };
0513 
0514 /* 0x0415 - Unicode alpha names */
0515 struct KRITAPSD_EXPORT ALPHA_NAMES_UNI_1045 : public PSDInterpretedResource {
0516     bool interpretBlock(QByteArray /*data*/) override
0517     {
0518         dbgFile << "Reading ALPHA_NAMES_UNI_1045";
0519         return true;
0520     }
0521 };
0522 
0523 /* 0x0416 - Indexed color table count */
0524 struct KRITAPSD_EXPORT IDX_COL_TAB_CNT_1046 : public PSDInterpretedResource {
0525     bool interpretBlock(QByteArray /*data*/) override
0526     {
0527         dbgFile << "Reading IDX_COL_TAB_CNT_1046";
0528         return true;
0529     }
0530 };
0531 
0532 /* 0x0417 - Index of transparent color (if any) */
0533 struct KRITAPSD_EXPORT IDX_TRANSPARENT_1047 : public PSDInterpretedResource {
0534     bool interpretBlock(QByteArray /*data*/) override
0535     {
0536         dbgFile << "Reading IDX_TRANSPARENT_1047";
0537         return true;
0538     }
0539 };
0540 
0541 /* 0x0419 - Global altitude */
0542 struct KRITAPSD_EXPORT GLOBAL_ALT_1049 : public PSDInterpretedResource {
0543     GLOBAL_ALT_1049()
0544         : altitude(30)
0545     {
0546     }
0547     bool interpretBlock(QByteArray data) override
0548     {
0549         dbgFile << "Reading GLOBAL_ALT_1049";
0550         QDataStream ds(data);
0551         ds.setByteOrder(QDataStream::BigEndian);
0552         ds >> altitude;
0553         return true;
0554     }
0555 
0556     bool createBlock(QByteArray &data) override
0557     {
0558         QBuffer buf(&data);
0559         startBlock(buf, PSDImageResourceSection::GLOBAL_ALT, 4);
0560         psdwrite(buf, (quint32)altitude);
0561         return true;
0562     }
0563 
0564     bool valid() override
0565     {
0566         return true;
0567     }
0568 
0569     QString displayText() override
0570     {
0571         return QString("Global Altitude: %1").arg(altitude);
0572     }
0573 
0574     qint32 altitude;
0575 };
0576 
0577 /* 0x041a - Slices */
0578 struct KRITAPSD_EXPORT SLICES_1050 : public PSDInterpretedResource {
0579     bool interpretBlock(QByteArray /*data*/) override
0580     {
0581         dbgFile << "Reading SLICES_1050";
0582         return true;
0583     }
0584 };
0585 
0586 /* 0x041b - Workflow URL - Unicode string */
0587 struct KRITAPSD_EXPORT WORKFLOW_URL_UNI_1051 : public PSDInterpretedResource {
0588     bool interpretBlock(QByteArray /*data*/) override
0589     {
0590         dbgFile << "Reading WORKFLOW_URL_UNI_1051";
0591         return true;
0592     }
0593 };
0594 
0595 /* 0x041c - Jump to XPEP (?) */
0596 struct KRITAPSD_EXPORT JUMP_TO_XPEP_1052 : public PSDInterpretedResource {
0597     bool interpretBlock(QByteArray /*data*/) override
0598     {
0599         dbgFile << "JUMP_TO_XPEP_1052";
0600         return true;
0601     }
0602 };
0603 
0604 /* 0x041d - Alpha IDs */
0605 struct KRITAPSD_EXPORT ALPHA_ID_1053 : public PSDInterpretedResource {
0606     bool interpretBlock(QByteArray /*data*/) override
0607     {
0608         dbgFile << "ALPHA_ID_1053";
0609         return true;
0610     }
0611 };
0612 
0613 /* 0x041e - URL list - unicode */
0614 struct KRITAPSD_EXPORT URL_LIST_UNI_1054 : public PSDInterpretedResource {
0615     bool interpretBlock(QByteArray /*data*/) override
0616     {
0617         dbgFile << "URL_LIST_UNI_1054";
0618         return true;
0619     }
0620 };
0621 
0622 /* 0x0421 - Version info */
0623 struct KRITAPSD_EXPORT VERSION_INFO_1057 : public PSDInterpretedResource {
0624     bool interpretBlock(QByteArray /*data*/) override
0625     {
0626         dbgFile << "VERSION_INFO_1057";
0627         return true;
0628     }
0629 };
0630 
0631 /* 0x0422 - Exif data block */
0632 struct KRITAPSD_EXPORT EXIF_DATA_1058 : public PSDInterpretedResource {
0633     bool interpretBlock(QByteArray /*data*/) override
0634     {
0635         dbgFile << "Reading EXIF_DATA_1058";
0636         return true;
0637     }
0638 };
0639 
0640 /* 0x0424 - XMP data block */
0641 struct KRITAPSD_EXPORT XMP_DATA_1060 : public PSDInterpretedResource {
0642     bool interpretBlock(QByteArray /*data*/) override
0643     {
0644         dbgFile << "Reading XMP_DATA_1060";
0645         return true;
0646     }
0647 };
0648 
0649 /* 0x07d0 - First path info block */
0650 struct KRITAPSD_EXPORT PATH_INFO_FIRST_2000 : public PSDInterpretedResource {
0651     bool interpretBlock(QByteArray /*data*/) override
0652     {
0653         dbgFile << "PATH_INFO_FIRST_2000";
0654         return true;
0655     }
0656 };
0657 
0658 /* 0x0bb6 - Last path info block */
0659 struct KRITAPSD_EXPORT PATH_INFO_LAST_2998 : public PSDInterpretedResource {
0660     bool interpretBlock(QByteArray /*data*/) override
0661     {
0662         dbgFile << "PATH_INFO_LAST_2998";
0663         return true;
0664     }
0665 };
0666 
0667 /* 0x0bb7 - Name of clipping path */
0668 struct KRITAPSD_EXPORT CLIPPING_PATH_2999 : public PSDInterpretedResource {
0669     bool interpretBlock(QByteArray /*data*/) override
0670     {
0671         dbgFile << "Reading CLIPPING_PATH_2999";
0672         return true;
0673     }
0674 };
0675 
0676 /* 0x2710 - Print flags */
0677 struct KRITAPSD_EXPORT PRINT_FLAGS_2_10000 : public PSDInterpretedResource {
0678     bool interpretBlock(QByteArray /*data*/) override
0679     {
0680         dbgFile << "Reading PRINT_FLAGS_2_10000";
0681         return true;
0682     }
0683 };
0684 
0685 #endif // PSD_RESOURCE_BLOCK_H