Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / qcms / src / iccread.c
index 9ee6b94..69b7141 100644 (file)
@@ -340,6 +340,7 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile)
 #define TAG_A2B0 0x41324230
 #define TAG_B2A0 0x42324130
 #define TAG_CHAD 0x63686164
+#define TAG_desc 0x64657363
 
 static struct tag *find_tag(struct tag_index index, uint32_t tag_id)
 {
@@ -353,6 +354,47 @@ static struct tag *find_tag(struct tag_index index, uint32_t tag_id)
        return tag;
 }
 
+#define DESC_TYPE 0x64657363 // 'desc'
+#define MLUC_TYPE 0x6d6c7563 // 'mluc'
+
+static bool read_tag_descType(qcms_profile *profile, struct mem_source *src, struct tag_index index, uint32_t tag_id)
+{
+       struct tag *tag = find_tag(index, tag_id);
+       if (tag) {
+               const uint32_t limit = sizeof profile->description;
+               uint32_t offset = tag->offset;
+               uint32_t type = read_u32(src, offset);
+               uint32_t length = read_u32(src, offset+8);
+               uint32_t i, description;
+               if (length && type == MLUC_TYPE) {
+                       length = read_u32(src, offset+20);
+                       if (!length || (length & 1) || (read_u32(src, offset+12) != 12))
+                               goto invalid_desc_tag;
+                       description = offset + read_u32(src, offset+24);
+                       if (!src->valid)
+                               goto invalid_desc_tag;
+               } else if (length && type == DESC_TYPE) {
+                       description = offset + 12;
+               } else {
+                       goto invalid_desc_tag;
+               }
+               if (length >= limit)
+                       length = limit - 1;
+               for (i = 0; i < length; ++i)
+                       profile->description[i] = read_u8(src, description+i);
+               profile->description[length] = 0;
+       } else {
+               goto invalid_desc_tag;
+       }
+
+       if (src->valid)
+               return true;
+
+invalid_desc_tag:
+       invalid_source(src, "invalid description");
+       return false;
+}
+
 #define XYZ_TYPE               0x58595a20 // 'XYZ '
 #define CURVE_TYPE             0x63757276 // 'curv'
 #define PARAMETRIC_CURVE_TYPE  0x70617261 // 'para'
@@ -493,19 +535,23 @@ static void read_nested_curveType(struct mem_source *src, struct curveType *(*cu
        uint32_t channel_offset = 0;
        int i;
        for (i = 0; i < num_channels; i++) {
-               uint32_t tag_len;
+               uint32_t tag_len = ~0;
 
                (*curveArray)[i] = read_curveType(src, curve_offset + channel_offset, &tag_len);
                if (!(*curveArray)[i]) {
                        invalid_source(src, "invalid nested curveType curve");
                }
 
+               if (tag_len == ~0) {
+                       invalid_source(src, "invalid nested curveType tag length");
+                       return;
+               }
+
                channel_offset += tag_len;
                // 4 byte aligned
                if ((tag_len % 4) != 0)
                        channel_offset += 4 - (tag_len % 4);
        }
-
 }
 
 static void mAB_release(struct lutmABType *lut)
@@ -988,6 +1034,9 @@ qcms_profile* qcms_profile_sRGB(void)
                return NO_MEM_PROFILE;
 
        profile = qcms_profile_create_rgb_with_table(D65, Rec709Primaries, table, 1024);
+       if (profile)
+               strcpy(profile->description, "sRGB IEC61966-2.1");
+
        free(table);
        return profile;
 }
@@ -1040,6 +1089,9 @@ qcms_profile* qcms_profile_from_memory(const void *mem, size_t size)
        if (!src->valid || !index.tags)
                goto invalid_tag_table;
 
+       if (!read_tag_descType(profile, src, index, TAG_desc))
+               goto invalid_tag_table;
+
        if (find_tag(index, TAG_CHAD)) {
                profile->chromaticAdaption = read_tag_s15Fixed16ArrayType(src, index, TAG_CHAD);
        } else {
@@ -1110,6 +1162,11 @@ invalid_profile:
        return INVALID_PROFILE;
 }
 
+qcms_bool qcms_profile_match(qcms_profile *p1, qcms_profile *p2)
+{
+    return memcmp(p1->description, p2->description, sizeof p1->description) == 0;
+}
+
 qcms_intent qcms_profile_get_rendering_intent(qcms_profile *profile)
 {
        return profile->rendering_intent;