/* * Add a range. */ static void add_range(fz_context *ctx, pdf_cmap *cmap, int low, int high, int flag, int offset) { /* Sanity check ranges */ if (low < 0 || low > 65535 || high < 0 || high > 65535 || low > high) { fz_warn(ctx, "range limits out of range in cmap %s", cmap->cmap_name); return; } /* If the range is too large to be represented, split it */ if (high - low > 0x3fff) { add_range(ctx, cmap, low, low+0x3fff, flag, offset); add_range(ctx, cmap, low+0x3fff, high, flag, offset+0x3fff); return; } if (cmap->rlen + 1 > cmap->rcap) { int new_cap = cmap->rcap > 1 ? (cmap->rcap * 3) / 2 : 256; cmap->ranges = fz_resize_array(ctx, cmap->ranges, new_cap, sizeof(pdf_range)); cmap->rcap = new_cap; } cmap->ranges[cmap->rlen].low = low; pdf_range_set_high(&cmap->ranges[cmap->rlen], high); pdf_range_set_flags(&cmap->ranges[cmap->rlen], flag); cmap->ranges[cmap->rlen].offset = offset; cmap->rlen ++; }
/* * Add a range. */ static void add_range(fz_context *ctx, pdf_cmap *cmap, int low, int high, int flag, int offset) { /* If the range is too large to be represented, split it */ if (high - low > 0x3fff) { add_range(ctx, cmap, low, low+0x3fff, flag, offset); add_range(ctx, cmap, low+0x3fff, high, flag, offset+0x3fff); return; } if (cmap->rlen + 1 > cmap->rcap) { cmap->rcap = cmap->rcap > 1 ? (cmap->rcap * 3) / 2 : 256; cmap->ranges = fz_resize_array(ctx, cmap->ranges, cmap->rcap, sizeof(pdf_range)); } cmap->ranges[cmap->rlen].low = low; pdf_range_set_high(&cmap->ranges[cmap->rlen], high); pdf_range_set_flags(&cmap->ranges[cmap->rlen], flag); cmap->ranges[cmap->rlen].offset = offset; cmap->rlen ++; }
void pdf_sort_cmap(fz_context *ctx, pdf_cmap *cmap) { pdf_range *a; /* last written range on output */ pdf_range *b; /* current range examined on input */ if (cmap->rlen == 0) return; qsort(cmap->ranges, cmap->rlen, sizeof(pdf_range), cmprange); if (cmap->tlen == USHRT_MAX) { fz_warn(ctx, "cmap table is full; will not combine ranges"); return; } a = cmap->ranges; b = cmap->ranges + 1; while (b < cmap->ranges + cmap->rlen) { /* ignore one-to-many mappings */ if (pdf_range_flags(b) == PDF_CMAP_MULTI) { *(++a) = *b; } /* input contiguous */ else if (pdf_range_high(a) + 1 == b->low) { /* output contiguous */ if (pdf_range_high(a) - a->low + a->offset + 1 == b->offset) { /* SR -> R and SS -> R and RR -> R and RS -> R */ if ((pdf_range_flags(a) == PDF_CMAP_SINGLE || pdf_range_flags(a) == PDF_CMAP_RANGE) && (pdf_range_high(b) - a->low <= 0x3fff)) { pdf_range_set_flags(a, PDF_CMAP_RANGE); pdf_range_set_high(a, pdf_range_high(b)); } /* LS -> L */ else if (pdf_range_flags(a) == PDF_CMAP_TABLE && pdf_range_flags(b) == PDF_CMAP_SINGLE && (pdf_range_high(b) - a->low <= 0x3fff)) { pdf_range_set_high(a, pdf_range_high(b)); add_table(ctx, cmap, b->offset); } /* LR -> LR */ else if (pdf_range_flags(a) == PDF_CMAP_TABLE && pdf_range_flags(b) == PDF_CMAP_RANGE) { *(++a) = *b; } /* XX -> XX */ else { *(++a) = *b; } } /* output separated */ else { /* SS -> L */ if (pdf_range_flags(a) == PDF_CMAP_SINGLE && pdf_range_flags(b) == PDF_CMAP_SINGLE) { pdf_range_set_flags(a, PDF_CMAP_TABLE); pdf_range_set_high(a, pdf_range_high(b)); add_table(ctx, cmap, a->offset); add_table(ctx, cmap, b->offset); a->offset = cmap->tlen - 2; } /* LS -> L */ else if (pdf_range_flags(a) == PDF_CMAP_TABLE && pdf_range_flags(b) == PDF_CMAP_SINGLE && (pdf_range_high(b) - a->low <= 0x3fff)) { pdf_range_set_high(a, pdf_range_high(b)); add_table(ctx, cmap, b->offset); } /* XX -> XX */ else { *(++a) = *b; } } } /* input separated: XX -> XX */ else { *(++a) = *b; } b ++; } cmap->rlen = a - cmap->ranges + 1; }