File indexing completed on 2024-05-12 15:59:40

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