diff --git a/pdf.c b/pdf.c index 8c08493c783bce59e6916a4b04952badd267c0eb..d169604736cd618e38d2b661d6c849aae9cf9d4c 100644 --- a/pdf.c +++ b/pdf.c @@ -632,6 +632,32 @@ act_dict_(const HParseResult *p, void *env) #define act_array_ h_act_flatten +HParsedToken * +act_longlength(const HParseResult *p, void *env) +{ + uint8_t length = H_CAST_UINT(p->ast); + uint8_t finallength = 257-length; + + return H_MAKE_UINT(finallength); +} + +HParsedToken * +act_longrun(const HParseResult *p, void *env) +{ + HCountedArray *seq = H_CAST_SEQ(p->ast); + HParsedToken **elements = h_seq_elements(p->ast); + HParsedToken *res = H_MAKE_SEQ(); + + uint8_t length = H_CAST_UINT(elements[0]); + uint8_t data = H_CAST_UINT(elements[1]); + + for (size_t len = 0; len < length; ++len) + { + h_seq_snoc(res, H_MAKE_UINT(data)); + } + + return res; +} /* * input grammar @@ -645,10 +671,30 @@ HParser *p_objdef; HParser *p_a85string; HParser *p_ahexstream; +HParser *p_rldstring; + /* continuations for h_bind() */ HParser *kstream(HAllocator *, const HParsedToken *, void *); HParser *kxstream(HAllocator *, const HParsedToken *, void *); +void +init_runlengthdecode_parser(struct Env *aux) +{ + H_RULE(rldeod, h_ch(0x80)); + H_ARULE(longlength, h_ch_range(0x81, 0xFF)); + H_RULE(shortlength, h_ch_range(0x1, 0x7F)); + + H_RULE(shortdata, h_uint8()); + H_RULE(longdata, h_uint8()); + + H_RULE(shortrun, h_length_value(shortlength, shortdata)); + H_ARULE(longrun, SEQ(longlength, longdata)); + + H_RULE(rldstring, SEQ(CHX(shortrun, longrun), IGN(rldeod))); + + p_rldstring = rldstring; +} + void init_parser(struct Env *aux) { @@ -928,6 +974,8 @@ init_parser(struct Env *aux) H_RULE(hs_end, CHX(hdigitpair, ahextruncated)); H_RULE(hexstream, SEQ(h_many(hdigitpair), hs_end)); + init_runlengthdecode_parser(aux); + /* global parser variables */ p_pdf = pdf; @@ -1308,6 +1356,21 @@ FlateDecode(const Dict *parms, HBytes b, HParser *p) return res; } +HParseResult * +RunLengthDecode(const Dict *parms, HBytes b, HParser *p) +{ + HParseResult *res; + + res = h_parse(p_rldstring, b.token, b.len); + if(!res) + { + fprintf(stderr, "parse error in RunLengthDecode filter\n"); + return NULL; + } + + return res; +} + /* * Decodes ASCII hexadecimal data into binary data. * parms should be empty, because the filter has no parameters @@ -1374,6 +1437,8 @@ decode_stream(const Dict *d, HBytes b, HParser *p) filter = ASCIIHexDecode; else if (bytes_eq(v->bytes, "ASCII85Decode")) filter = ASCII85Decode; + else if (bytes_eq(v->bytes, "RunLengthDecode")) + filter = RunLengthDecode; else return NULL; /* filter not supported */