| 1 | #include <stdio.h> |
|---|
| 2 | #include <string.h> |
|---|
| 3 | #include <malloc.h> |
|---|
| 4 | #include "utfStruct.h" |
|---|
| 5 | #include "utfRaster.h" |
|---|
| 6 | |
|---|
| 7 | //#define _SUBPIXEL_DEBUG_ON |
|---|
| 8 | #ifdef _SUBPIXEL_DEBUG_ON |
|---|
| 9 | #include <stdio.h> |
|---|
| 10 | static FILE* dbg_fp; |
|---|
| 11 | static char space[] = " "; |
|---|
| 12 | static char* tab = space + sizeof(space); |
|---|
| 13 | #define _TI() tab -= 2 |
|---|
| 14 | #define _TD() tab += 2 |
|---|
| 15 | #define _SF(arg) fprintf(dbg_fp, tab); fprintf(dbg_fp, "### Start: "); fprintf arg; fprintf(dbg_fp, " ###\n"); _TI() |
|---|
| 16 | #define _EF(arg) _TD(); fprintf(dbg_fp, tab); fprintf(dbg_fp, "--- End: "); fprintf arg; fprintf(dbg_fp, " ---\n") |
|---|
| 17 | #define _OO(arg) fprintf(dbg_fp, tab); fprintf arg; fprintf(dbg_fp, "\n") |
|---|
| 18 | void OpenFreeTypeDebugFile() {dbg_fp = fopen("\\o.txt", "wt");} |
|---|
| 19 | void CloseFreeTypeDebugFile() {fclose(dbg_fp);} |
|---|
| 20 | #else |
|---|
| 21 | #define _TI() |
|---|
| 22 | #define _TD() |
|---|
| 23 | #define _SF(arg) |
|---|
| 24 | #define _EF(arg) |
|---|
| 25 | #define _OO(arg) |
|---|
| 26 | void OpenFreeTypeDebugFile() {} |
|---|
| 27 | void CloseFreeTypeDebugFile() {} |
|---|
| 28 | #endif |
|---|
| 29 | |
|---|
| 30 | #define PIXEL_BITS 8 |
|---|
| 31 | #define ONE_PIXEL (1L << PIXEL_BITS) |
|---|
| 32 | #define TRUNC(x) ((TCoord)((x) >> PIXEL_BITS)) |
|---|
| 33 | #define SUBPIXELS(x)((TPos)(x) << PIXEL_BITS) |
|---|
| 34 | #define UPSCALE(x)((x) <<(PIXEL_BITS - 6)) |
|---|
| 35 | #define DOWNSCALE(x)((x) >>(PIXEL_BITS - 6)) |
|---|
| 36 | #define FT_MAX_GRAY_SPANS 32 |
|---|
| 37 | |
|---|
| 38 | #define FT_CURVE_TAG(flag) (flag & 3) |
|---|
| 39 | #define FT_CURVE_TAG_ON 1 |
|---|
| 40 | #define FT_CURVE_TAG_CONIC 0 |
|---|
| 41 | #define FT_CURVE_TAG_CUBIC 2 |
|---|
| 42 | |
|---|
| 43 | typedef int TCoord; /* integer scanline/pixel coordinate */ |
|---|
| 44 | typedef long TPos; /* sub-pixel coordinate */ |
|---|
| 45 | typedef int TArea; |
|---|
| 46 | typedef signed long FT_Pos; |
|---|
| 47 | typedef int FT_Int; |
|---|
| 48 | typedef unsigned int FT_UInt; |
|---|
| 49 | |
|---|
| 50 | typedef struct FT_Vector |
|---|
| 51 | { |
|---|
| 52 | FT_Pos x; |
|---|
| 53 | FT_Pos y; |
|---|
| 54 | } FT_Vector; |
|---|
| 55 | |
|---|
| 56 | typedef struct FT_Outline |
|---|
| 57 | { |
|---|
| 58 | int nPath; |
|---|
| 59 | int nPoint; |
|---|
| 60 | FT_Vector points[4096]; |
|---|
| 61 | UT_U8* on; |
|---|
| 62 | UT_I16* endPointIndex; |
|---|
| 63 | } FT_Outline; |
|---|
| 64 | |
|---|
| 65 | typedef struct FT_Bitmap |
|---|
| 66 | { |
|---|
| 67 | int rows; |
|---|
| 68 | int width; |
|---|
| 69 | int pitch; |
|---|
| 70 | unsigned char* buffer_; |
|---|
| 71 | } FT_Bitmap; |
|---|
| 72 | |
|---|
| 73 | typedef struct FT_BBox |
|---|
| 74 | { |
|---|
| 75 | FT_Pos xMin, yMin; |
|---|
| 76 | FT_Pos xMax, yMax; |
|---|
| 77 | } FT_BBox; |
|---|
| 78 | |
|---|
| 79 | typedef struct FT_Span |
|---|
| 80 | { |
|---|
| 81 | short x; |
|---|
| 82 | unsigned short len; |
|---|
| 83 | unsigned char coverage; |
|---|
| 84 | } FT_Span; |
|---|
| 85 | |
|---|
| 86 | typedef struct FT_Cell |
|---|
| 87 | { |
|---|
| 88 | TCoord x; |
|---|
| 89 | TCoord y; |
|---|
| 90 | int cover; |
|---|
| 91 | TArea area; |
|---|
| 92 | } FT_Cell; |
|---|
| 93 | |
|---|
| 94 | typedef struct FT_Raster |
|---|
| 95 | { |
|---|
| 96 | FT_Cell* cells; |
|---|
| 97 | int max_cells; |
|---|
| 98 | int num_cells; |
|---|
| 99 | TPos min_ex, max_ex; |
|---|
| 100 | TPos min_ey, max_ey; |
|---|
| 101 | TArea area; |
|---|
| 102 | int cover; |
|---|
| 103 | int invalid; |
|---|
| 104 | TCoord ex, ey; |
|---|
| 105 | TCoord cx, cy; |
|---|
| 106 | TPos x, y; |
|---|
| 107 | TPos last_ey; |
|---|
| 108 | FT_Vector bez_stack[32 * 3 + 1]; |
|---|
| 109 | int lev_stack[32]; |
|---|
| 110 | FT_Outline outline; |
|---|
| 111 | FT_Bitmap bitmap; |
|---|
| 112 | FT_Span gray_spans[FT_MAX_GRAY_SPANS]; |
|---|
| 113 | int num_gray_spans; |
|---|
| 114 | int span_y; |
|---|
| 115 | int conic_level; |
|---|
| 116 | int cubic_level; |
|---|
| 117 | } FT_Raster; |
|---|
| 118 | |
|---|
| 119 | /* |
|---|
| 120 | void DispBitmap(FT_Bitmap* bitmap) |
|---|
| 121 | { |
|---|
| 122 | FILE* fp = dbg_fp; //fopen("\\o.txt", "wt"); |
|---|
| 123 | unsigned char* p = bitmap->buffer_; |
|---|
| 124 | int y; |
|---|
| 125 | for (y=0; y<bitmap->rows; y++) |
|---|
| 126 | { |
|---|
| 127 | int i, x = 0; |
|---|
| 128 | for (i=0; i<bitmap->width; i+=3,x++) |
|---|
| 129 | { |
|---|
| 130 | int r = p[i+0]; |
|---|
| 131 | int g = p[i+1]; |
|---|
| 132 | int b = p[i+2]; |
|---|
| 133 | fprintf(fp, "%02x%02x%02x", r, g, b); |
|---|
| 134 | } |
|---|
| 135 | p += bitmap->pitch; |
|---|
| 136 | fprintf(fp, "\n"); |
|---|
| 137 | } |
|---|
| 138 | fprintf(fp, "\n"); |
|---|
| 139 | //fclose(fp); |
|---|
| 140 | } |
|---|
| 141 | */ |
|---|
| 142 | |
|---|
| 143 | static void gray_init_cells(FT_Raster* raster, void* buffer, long byte_size) |
|---|
| 144 | { |
|---|
| 145 | raster->cells = (FT_Cell*)buffer; |
|---|
| 146 | raster->max_cells = byte_size / sizeof(FT_Cell); |
|---|
| 147 | raster->num_cells = 0; |
|---|
| 148 | raster->area = 0; |
|---|
| 149 | raster->cover = 0; |
|---|
| 150 | raster->invalid = 1; |
|---|
| 151 | } |
|---|
| 152 | |
|---|
| 153 | static void gray_compute_cbox(FT_Raster* raster) |
|---|
| 154 | { |
|---|
| 155 | int i = 0; |
|---|
| 156 | FT_Outline* outline = &raster->outline; |
|---|
| 157 | FT_Vector* vec = outline->points; |
|---|
| 158 | FT_Vector* limit = vec + outline->nPoint; |
|---|
| 159 | _SF((dbg_fp, "gray_compute_cbox()")); |
|---|
| 160 | if (outline->nPoint <= 0) |
|---|
| 161 | { |
|---|
| 162 | raster->min_ex = raster->max_ex = 0; |
|---|
| 163 | raster->min_ey = raster->max_ey = 0; |
|---|
| 164 | _EF((dbg_fp, "gray_compute_cbox()")); |
|---|
| 165 | return; |
|---|
| 166 | } |
|---|
| 167 | raster->min_ex = raster->max_ex = vec->x; |
|---|
| 168 | raster->min_ey = raster->max_ey = vec->y; |
|---|
| 169 | _OO((dbg_fp, "point[%d] = %4d, %4d", i, vec->x, vec->y)); i++; |
|---|
| 170 | vec++; |
|---|
| 171 | for (; vec < limit; vec++) |
|---|
| 172 | { |
|---|
| 173 | TPos x = vec->x; |
|---|
| 174 | TPos y = vec->y; |
|---|
| 175 | if (x < raster->min_ex) raster->min_ex = x; |
|---|
| 176 | if (x > raster->max_ex) raster->max_ex = x; |
|---|
| 177 | if (y < raster->min_ey) raster->min_ey = y; |
|---|
| 178 | if (y > raster->max_ey) raster->max_ey = y; |
|---|
| 179 | _OO((dbg_fp, "point[%d] = %4d, %4d", i, vec->x, vec->y)); i++; |
|---|
| 180 | } |
|---|
| 181 | raster->min_ex = raster->min_ex >> 6; |
|---|
| 182 | raster->min_ey = raster->min_ey >> 6; |
|---|
| 183 | raster->max_ex = (raster->max_ex + 63) >> 6; |
|---|
| 184 | raster->max_ey = (raster->max_ey + 63) >> 6; |
|---|
| 185 | _OO((dbg_fp, "min_ex=%d, min_ey=%d, max_ex=%d, max_ey=%d", raster->min_ex, raster->min_ey, raster->max_ex, raster->max_ey)); |
|---|
| 186 | _EF((dbg_fp, "gray_compute_cbox()")); |
|---|
| 187 | } |
|---|
| 188 | |
|---|
| 189 | static void gray_record_cell(FT_Raster* raster) |
|---|
| 190 | { |
|---|
| 191 | FT_Cell* cell; |
|---|
| 192 | _SF((dbg_fp, "gray_record_cell()")); |
|---|
| 193 | if (!raster->invalid && (raster->area | raster->cover)) |
|---|
| 194 | { |
|---|
| 195 | cell = raster->cells + raster->num_cells++; |
|---|
| 196 | cell->x = (TCoord)(raster->ex - raster->min_ex); |
|---|
| 197 | cell->y = (TCoord)(raster->ey - raster->min_ey); |
|---|
| 198 | cell->area = raster->area; |
|---|
| 199 | cell->cover = raster->cover; |
|---|
| 200 | _OO((dbg_fp, "cell[%d] x=%d, y=%d, area=%d, cover=%d", raster->num_cells-1, cell->x, cell->y, cell->area, cell->cover)); |
|---|
| 201 | } |
|---|
| 202 | _EF((dbg_fp, "gray_record_cell()")); |
|---|
| 203 | } |
|---|
| 204 | |
|---|
| 205 | static void gray_set_cell(FT_Raster* raster, TCoord ex, TCoord ey) |
|---|
| 206 | { |
|---|
| 207 | int record = 0, clean = 1; |
|---|
| 208 | int invalid = (ey < raster->min_ey || ey >= raster->max_ey || ex >= raster->max_ex); |
|---|
| 209 | _SF((dbg_fp, "gray_set_cell(ex=%d, ey=%d)", ex, ey)); |
|---|
| 210 | if (!invalid) |
|---|
| 211 | { |
|---|
| 212 | if (ex < raster->min_ex) |
|---|
| 213 | ex = (TCoord)(raster->min_ex - 1); |
|---|
| 214 | if (ex != raster->ex || ey != raster->ey) |
|---|
| 215 | record = 1; |
|---|
| 216 | else |
|---|
| 217 | clean = raster->invalid; /* do not clean if we didn't move from */ |
|---|
| 218 | } |
|---|
| 219 | if (raster->invalid != invalid || record) |
|---|
| 220 | gray_record_cell(raster); |
|---|
| 221 | if (clean) |
|---|
| 222 | { |
|---|
| 223 | raster->area = 0; |
|---|
| 224 | raster->cover = 0; |
|---|
| 225 | } |
|---|
| 226 | raster->invalid = invalid; |
|---|
| 227 | raster->ex = ex; |
|---|
| 228 | raster->ey = ey; |
|---|
| 229 | _OO((dbg_fp, "raster: ex=%d, ey=%d", raster->ex, raster->ey)); |
|---|
| 230 | _EF((dbg_fp, "gray_set_cell()")); |
|---|
| 231 | } |
|---|
| 232 | |
|---|
| 233 | static void gray_start_cell(FT_Raster* raster, TCoord ex, TCoord ey) |
|---|
| 234 | { |
|---|
| 235 | _SF((dbg_fp, "gray_start_cell(ex=%d, ey=%d)", ex, ey)); |
|---|
| 236 | if (ex < raster->min_ex) ex = (TCoord)(raster->min_ex - 1); |
|---|
| 237 | raster->area = 0; |
|---|
| 238 | raster->cover = 0; |
|---|
| 239 | raster->ex = ex; |
|---|
| 240 | raster->ey = ey; |
|---|
| 241 | raster->last_ey = SUBPIXELS(ey); |
|---|
| 242 | raster->invalid = 0; |
|---|
| 243 | _OO((dbg_fp, "raster: area=%d, cover=%d", raster->area, raster->cover)); |
|---|
| 244 | _OO((dbg_fp, "raster: ex=%d, ey=%d, last_ey=%d", raster->ex, raster->ey, raster->last_ey)); |
|---|
| 245 | gray_set_cell(raster, ex, ey); |
|---|
| 246 | _EF((dbg_fp, "gray_start_cell()")); |
|---|
| 247 | } |
|---|
| 248 | |
|---|
| 249 | static void gray_render_scanline(FT_Raster* raster, TCoord ey, TPos x1, TCoord y1, TPos x2, TCoord y2) |
|---|
| 250 | { |
|---|
| 251 | TCoord ex1, ex2, fx1, fx2, delta; |
|---|
| 252 | long p, first, dx; |
|---|
| 253 | int incr, lift, mod, rem; |
|---|
| 254 | _SF((dbg_fp, "gray_render_scanline(ey=%d, x1=%d, y1=%d, x2=%d, y2=%d)", ey, x1, y1, x2, y2)); |
|---|
| 255 | dx = x2 - x1; |
|---|
| 256 | ex1 = TRUNC(x1); /* if (ex1 >= raster->max_ex) ex1 = raster->max_ex-1; */ |
|---|
| 257 | ex2 = TRUNC(x2); /* if (ex2 >= raster->max_ex) ex2 = raster->max_ex-1; */ |
|---|
| 258 | fx1 = (TCoord)(x1 - SUBPIXELS(ex1)); |
|---|
| 259 | fx2 = (TCoord)(x2 - SUBPIXELS(ex2)); |
|---|
| 260 | _OO((dbg_fp, "dx=%d, ex1=%d, ex2=%d, fx1=%d, fx2=%d", dx, ex1, ex2, fx1, fx2)); |
|---|
| 261 | if (y1 == y2) |
|---|
| 262 | { |
|---|
| 263 | _OO((dbg_fp, "if (y1 == y2)")); |
|---|
| 264 | _TI(); |
|---|
| 265 | gray_set_cell(raster, ex2, ey); |
|---|
| 266 | _TD(); |
|---|
| 267 | _EF((dbg_fp, "gray_render_scanline(y1 == y2)")); |
|---|
| 268 | return; |
|---|
| 269 | } |
|---|
| 270 | if (ex1 == ex2) |
|---|
| 271 | { |
|---|
| 272 | _OO((dbg_fp, "if (ex1 == ex2)")); |
|---|
| 273 | _TI(); |
|---|
| 274 | delta = y2 - y1; |
|---|
| 275 | raster->area += (TArea)(fx1 + fx2) * delta; |
|---|
| 276 | raster->cover += delta; |
|---|
| 277 | _OO((dbg_fp, "gray_set_cell(area=%d, cover=%d)", raster->area, raster->cover)); |
|---|
| 278 | _TD(); |
|---|
| 279 | _EF((dbg_fp, "gray_render_scanline(ex1 == ex2)")); |
|---|
| 280 | return; |
|---|
| 281 | } |
|---|
| 282 | p = (ONE_PIXEL - fx1) * (y2 - y1); |
|---|
| 283 | first = ONE_PIXEL; |
|---|
| 284 | incr = 1; |
|---|
| 285 | if (dx < 0) |
|---|
| 286 | { |
|---|
| 287 | p = fx1 * (y2 - y1); |
|---|
| 288 | first = 0; |
|---|
| 289 | incr = -1; |
|---|
| 290 | dx = -dx; |
|---|
| 291 | } |
|---|
| 292 | delta = (TCoord)(p / dx); |
|---|
| 293 | mod = (TCoord)(p % dx); |
|---|
| 294 | if (mod < 0) |
|---|
| 295 | { |
|---|
| 296 | delta--; |
|---|
| 297 | mod += (TCoord)dx; |
|---|
| 298 | } |
|---|
| 299 | _OO((dbg_fp, "p=%d, first=%d, incr=%d, delta=%d, mod=%d", p, first, incr, delta, mod)); |
|---|
| 300 | raster->area += (TArea)(fx1 + first) * delta; |
|---|
| 301 | raster->cover += delta; |
|---|
| 302 | _OO((dbg_fp, "raster: area=%d, cover=%d", raster->area, raster->cover)); |
|---|
| 303 | ex1 += incr; |
|---|
| 304 | gray_set_cell(raster, ex1, ey); |
|---|
| 305 | y1 += delta; |
|---|
| 306 | if (ex1 != ex2) |
|---|
| 307 | { |
|---|
| 308 | _OO((dbg_fp, "if (ex1 != ex2)")); |
|---|
| 309 | _TI(); |
|---|
| 310 | p = ONE_PIXEL * (y2 - y1 + delta); |
|---|
| 311 | lift = (TCoord)(p / dx); |
|---|
| 312 | rem = (TCoord)(p % dx); |
|---|
| 313 | if (rem < 0) |
|---|
| 314 | { |
|---|
| 315 | lift--; |
|---|
| 316 | rem += (TCoord)dx; |
|---|
| 317 | } |
|---|
| 318 | mod -= dx; |
|---|
| 319 | _OO((dbg_fp, "ex1=%d, ex2=%d, mod=%d", ex1, ex2)); |
|---|
| 320 | _OO((dbg_fp, "p=%d, lift=%d, rem=%d, mod=%d, delta=%d", p, lift, rem, mod, delta)); |
|---|
| 321 | _TI(); |
|---|
| 322 | while (ex1 != ex2) |
|---|
| 323 | { |
|---|
| 324 | delta = lift; |
|---|
| 325 | mod += rem; |
|---|
| 326 | if (mod >= 0) |
|---|
| 327 | { |
|---|
| 328 | mod -= (TCoord)dx; |
|---|
| 329 | delta++; |
|---|
| 330 | } |
|---|
| 331 | _OO((dbg_fp, "ex1=%d, ex2=%d, mod=%d", ex1, ex2)); |
|---|
| 332 | _OO((dbg_fp, "p=%d, lift=%d, rem=%d, mod=%d, delta=%d", p, lift, rem, mod, delta)); |
|---|
| 333 | raster->area += (TArea)ONE_PIXEL * delta; |
|---|
| 334 | raster->cover += delta; |
|---|
| 335 | _OO((dbg_fp, "raster: area=%d, cover=%d", raster->area, raster->cover)); |
|---|
| 336 | y1 += delta; |
|---|
| 337 | ex1 += incr; |
|---|
| 338 | gray_set_cell(raster, ex1, ey); |
|---|
| 339 | } |
|---|
| 340 | _TD(); |
|---|
| 341 | _TD(); |
|---|
| 342 | } |
|---|
| 343 | delta = y2 - y1; |
|---|
| 344 | raster->area += (TArea)(fx2 + ONE_PIXEL - first) * delta; |
|---|
| 345 | raster->cover += delta; |
|---|
| 346 | _OO((dbg_fp, "raster: area=%d, cover=%d", raster->area, raster->cover)); |
|---|
| 347 | _EF((dbg_fp, "gray_render_scanline()")); |
|---|
| 348 | } |
|---|
| 349 | |
|---|
| 350 | static void gray_render_line(FT_Raster* raster, TPos to_x, TPos to_y) |
|---|
| 351 | { |
|---|
| 352 | TCoord ey1, ey2, fy1, fy2; |
|---|
| 353 | TPos dx, dy, x, x2; |
|---|
| 354 | long p, first; |
|---|
| 355 | int delta, rem, mod, lift, incr; |
|---|
| 356 | _SF((dbg_fp, "gray_render_line(to_x=%d, to_y=%d)", to_x, to_y)); |
|---|
| 357 | ey1 = TRUNC(raster->last_ey); |
|---|
| 358 | ey2 = TRUNC(to_y); /* if (ey2 >= raster->max_ey) ey2 = raster->max_ey-1; */ |
|---|
| 359 | fy1 = (TCoord)(raster->y - raster->last_ey); |
|---|
| 360 | fy2 = (TCoord)(to_y - SUBPIXELS(ey2)); |
|---|
| 361 | dx = to_x - raster->x; |
|---|
| 362 | dy = to_y - raster->y; |
|---|
| 363 | _OO((dbg_fp, "dx=%d, dy=%d", dx, dy)); |
|---|
| 364 | _OO((dbg_fp, "ey1=%d, ey2=%d, fy1=%d, fy2=%d", ey1, ey2, fy1, fy2)); |
|---|
| 365 | { |
|---|
| 366 | TCoord min, max; |
|---|
| 367 | min = ey1; |
|---|
| 368 | max = ey2; |
|---|
| 369 | if (ey1 > ey2) |
|---|
| 370 | { |
|---|
| 371 | min = ey2; |
|---|
| 372 | max = ey1; |
|---|
| 373 | } |
|---|
| 374 | if (min >= raster->max_ey || max < raster->min_ey) goto End; |
|---|
| 375 | } |
|---|
| 376 | if (ey1 == ey2) |
|---|
| 377 | { |
|---|
| 378 | _OO((dbg_fp, "if (ey1 == ey2)")); |
|---|
| 379 | _TI(); |
|---|
| 380 | gray_render_scanline(raster, ey1, raster->x, fy1, to_x, fy2); |
|---|
| 381 | _TD(); |
|---|
| 382 | goto End; |
|---|
| 383 | } |
|---|
| 384 | incr = 1; |
|---|
| 385 | if (dx == 0) |
|---|
| 386 | { |
|---|
| 387 | TCoord ex = TRUNC(raster->x); |
|---|
| 388 | TCoord two_fx = (TCoord)((raster->x - SUBPIXELS(ex)) << 1); |
|---|
| 389 | TPos area; |
|---|
| 390 | _OO((dbg_fp, "if (dx == 0)")); |
|---|
| 391 | _TI(); |
|---|
| 392 | first = ONE_PIXEL; |
|---|
| 393 | if (dy < 0) |
|---|
| 394 | { |
|---|
| 395 | first = 0; |
|---|
| 396 | incr = -1; |
|---|
| 397 | } |
|---|
| 398 | delta = (int)(first - fy1); |
|---|
| 399 | raster->area += (TArea)two_fx * delta; |
|---|
| 400 | raster->cover += delta; |
|---|
| 401 | ey1 += incr; |
|---|
| 402 | _OO((dbg_fp, "raster: area=%d, cover=%d,,, ey1=%d", raster->area, raster->cover, ey1)); |
|---|
| 403 | gray_set_cell(raster, ex, ey1); |
|---|
| 404 | delta = (int)(first + first - ONE_PIXEL); |
|---|
| 405 | area = (TArea)two_fx * delta; |
|---|
| 406 | _TI(); |
|---|
| 407 | while (ey1 != ey2) |
|---|
| 408 | { |
|---|
| 409 | raster->area += area; |
|---|
| 410 | raster->cover += delta; |
|---|
| 411 | ey1 += incr; |
|---|
| 412 | _OO((dbg_fp, "raster: area=%d, cover=%d,,, ey1=%d", raster->area, raster->cover, ey1)); |
|---|
| 413 | gray_set_cell(raster, ex, ey1); |
|---|
| 414 | } |
|---|
| 415 | _TD(); |
|---|
| 416 | delta = (int)(fy2 - ONE_PIXEL + first); |
|---|
| 417 | raster->area += (TArea)two_fx * delta; |
|---|
| 418 | raster->cover += delta; |
|---|
| 419 | _OO((dbg_fp, "raster: area=%d, cover=%d", raster->area, raster->cover)); |
|---|
| 420 | _TD(); |
|---|
| 421 | goto End; |
|---|
| 422 | } |
|---|
| 423 | p = (ONE_PIXEL - fy1) * dx; |
|---|
| 424 | first = ONE_PIXEL; |
|---|
| 425 | incr = 1; |
|---|
| 426 | if (dy < 0) |
|---|
| 427 | { |
|---|
| 428 | p = fy1 * dx; |
|---|
| 429 | first = 0; |
|---|
| 430 | incr = -1; |
|---|
| 431 | dy = -dy; |
|---|
| 432 | } |
|---|
| 433 | delta = (int)(p / dy); |
|---|
| 434 | mod = (int)(p % dy); |
|---|
| 435 | if (mod < 0) |
|---|
| 436 | { |
|---|
| 437 | delta--; |
|---|
| 438 | mod += (TCoord)dy; |
|---|
| 439 | } |
|---|
| 440 | x = raster->x + delta; |
|---|
| 441 | _OO((dbg_fp, "p=%d, first=%d, incr=%d, delta=%d, mod=%d, dy=%d", p, first, incr, delta, mod, dy)); |
|---|
| 442 | gray_render_scanline(raster, ey1, raster->x, fy1, x,(TCoord)first); |
|---|
| 443 | ey1 += incr; |
|---|
| 444 | gray_set_cell(raster, TRUNC(x), ey1); |
|---|
| 445 | if (ey1 != ey2) |
|---|
| 446 | { |
|---|
| 447 | _OO((dbg_fp, "if (ey1 != ey2)")); |
|---|
| 448 | _TI(); |
|---|
| 449 | p = ONE_PIXEL * dx; |
|---|
| 450 | lift = (int)(p / dy); |
|---|
| 451 | rem = (int)(p % dy); |
|---|
| 452 | if (rem < 0) |
|---|
| 453 | { |
|---|
| 454 | lift--; |
|---|
| 455 | rem += (int)dy; |
|---|
| 456 | } |
|---|
| 457 | mod -= (int)dy; |
|---|
| 458 | _OO((dbg_fp, "ey1=%d, ey2=%d, mod=%d", ey1, ey2)); |
|---|
| 459 | _OO((dbg_fp, "p=%d, lift=%d, rem=%d, mod=%d, delta=%d", p, lift, rem, mod, delta)); |
|---|
| 460 | _TI(); |
|---|
| 461 | while (ey1 != ey2) |
|---|
| 462 | { |
|---|
| 463 | delta = lift; |
|---|
| 464 | mod += rem; |
|---|
| 465 | if (mod >= 0) |
|---|
| 466 | { |
|---|
| 467 | mod -= (int)dy; |
|---|
| 468 | delta++; |
|---|
| 469 | } |
|---|
| 470 | x2 = x + delta; |
|---|
| 471 | _OO((dbg_fp, "ey1=%d, ey2=%d, mod=%d", ey1, ey2)); |
|---|
| 472 | _OO((dbg_fp, "p=%d, lift=%d, rem=%d, mod=%d, delta=%d", p, lift, rem, mod, delta)); |
|---|
| 473 | gray_render_scanline(raster, ey1, x, (TCoord)(ONE_PIXEL - first), x2, (TCoord)first); |
|---|
| 474 | x = x2; |
|---|
| 475 | ey1 += incr; |
|---|
| 476 | gray_set_cell(raster, TRUNC(x), ey1); |
|---|
| 477 | } |
|---|
| 478 | _TD(); |
|---|
| 479 | _TD(); |
|---|
| 480 | } |
|---|
| 481 | gray_render_scanline(raster, ey1, x, (TCoord)(ONE_PIXEL - first), to_x, fy2); |
|---|
| 482 | End: |
|---|
| 483 | raster->x = to_x; |
|---|
| 484 | raster->y = to_y; |
|---|
| 485 | raster->last_ey = SUBPIXELS(ey2); |
|---|
| 486 | _OO((dbg_fp, "raster: area=%d, cover=%d", raster->area, raster->cover)); |
|---|
| 487 | _EF((dbg_fp, "gray_render_line()")); |
|---|
| 488 | } |
|---|
| 489 | |
|---|
| 490 | static void gray_split_conic(FT_Vector* base) |
|---|
| 491 | { |
|---|
| 492 | TPos a, b; |
|---|
| 493 | base[4].x = base[2].x; |
|---|
| 494 | b = base[1].x; |
|---|
| 495 | a = base[3].x = (base[2].x + b) / 2; |
|---|
| 496 | b = base[1].x = (base[0].x + b) / 2; |
|---|
| 497 | base[2].x = (a + b) / 2; |
|---|
| 498 | base[4].y = base[2].y; |
|---|
| 499 | b = base[1].y; |
|---|
| 500 | a = base[3].y = (base[2].y + b) / 2; |
|---|
| 501 | b = base[1].y = (base[0].y + b) / 2; |
|---|
| 502 | base[2].y = (a + b) / 2; |
|---|
| 503 | } |
|---|
| 504 | |
|---|
| 505 | static void gray_render_conic(FT_Raster* raster, FT_Vector* control, FT_Vector* to) |
|---|
| 506 | { |
|---|
| 507 | TPos dx, dy; |
|---|
| 508 | int top, level; |
|---|
| 509 | int* levels; |
|---|
| 510 | FT_Vector* arc; |
|---|
| 511 | dx = DOWNSCALE(raster->x) + to->x -(control->x << 1); |
|---|
| 512 | if (dx < 0) |
|---|
| 513 | dx = -dx; |
|---|
| 514 | dy = DOWNSCALE(raster->y) + to->y -(control->y << 1); |
|---|
| 515 | if (dy < 0) |
|---|
| 516 | dy = -dy; |
|---|
| 517 | if (dx < dy) |
|---|
| 518 | dx = dy; |
|---|
| 519 | |
|---|
| 520 | level = 1; |
|---|
| 521 | dx = dx / raster->conic_level; |
|---|
| 522 | while (dx > 0) |
|---|
| 523 | { |
|---|
| 524 | dx >>= 2; |
|---|
| 525 | level++; |
|---|
| 526 | } |
|---|
| 527 | |
|---|
| 528 | /* a shortcut to speed things up */ |
|---|
| 529 | if (level <= 1) |
|---|
| 530 | { |
|---|
| 531 | /* we compute the mid-point directly in order to avoid */ |
|---|
| 532 | /* calling gray_split_conic() */ |
|---|
| 533 | TPos to_x, to_y, mid_x, mid_y; |
|---|
| 534 | |
|---|
| 535 | |
|---|
| 536 | to_x = UPSCALE(to->x); |
|---|
| 537 | to_y = UPSCALE(to->y); |
|---|
| 538 | mid_x = (raster->x + to_x + 2 * UPSCALE(control->x)) / 4; |
|---|
| 539 | mid_y = (raster->y + to_y + 2 * UPSCALE(control->y)) / 4; |
|---|
| 540 | |
|---|
| 541 | gray_render_line(raster, mid_x, mid_y); |
|---|
| 542 | gray_render_line(raster, to_x, to_y); |
|---|
| 543 | return; |
|---|
| 544 | } |
|---|
| 545 | |
|---|
| 546 | arc = raster->bez_stack; |
|---|
| 547 | levels = raster->lev_stack; |
|---|
| 548 | top = 0; |
|---|
| 549 | levels[0] = level; |
|---|
| 550 | |
|---|
| 551 | arc[0].x = UPSCALE(to->x); |
|---|
| 552 | arc[0].y = UPSCALE(to->y); |
|---|
| 553 | arc[1].x = UPSCALE(control->x); |
|---|
| 554 | arc[1].y = UPSCALE(control->y); |
|---|
| 555 | arc[2].x = raster->x; |
|---|
| 556 | arc[2].y = raster->y; |
|---|
| 557 | |
|---|
| 558 | while (top >= 0) |
|---|
| 559 | { |
|---|
| 560 | level = levels[top]; |
|---|
| 561 | if (level > 1) |
|---|
| 562 | { |
|---|
| 563 | /* check that the arc crosses the current band */ |
|---|
| 564 | TPos min, max, y; |
|---|
| 565 | |
|---|
| 566 | |
|---|
| 567 | min = max = arc[0].y; |
|---|
| 568 | |
|---|
| 569 | y = arc[1].y; |
|---|
| 570 | if (y < min) min = y; |
|---|
| 571 | if (y > max) max = y; |
|---|
| 572 | |
|---|
| 573 | y = arc[2].y; |
|---|
| 574 | if (y < min) min = y; |
|---|
| 575 | if (y > max) max = y; |
|---|
| 576 | |
|---|
| 577 | if (TRUNC(min) >= raster->max_ey || TRUNC(max) < raster->min_ey) |
|---|
| 578 | goto Draw; |
|---|
| 579 | |
|---|
| 580 | gray_split_conic(arc); |
|---|
| 581 | arc += 2; |
|---|
| 582 | top++; |
|---|
| 583 | levels[top] = levels[top - 1] = level - 1; |
|---|
| 584 | continue; |
|---|
| 585 | } |
|---|
| 586 | |
|---|
| 587 | Draw: |
|---|
| 588 | { |
|---|
| 589 | TPos to_x, to_y, mid_x, mid_y; |
|---|
| 590 | |
|---|
| 591 | |
|---|
| 592 | to_x = arc[0].x; |
|---|
| 593 | to_y = arc[0].y; |
|---|
| 594 | mid_x = (raster->x + to_x + 2 * arc[1].x) / 4; |
|---|
| 595 | mid_y = (raster->y + to_y + 2 * arc[1].y) / 4; |
|---|
| 596 | |
|---|
| 597 | gray_render_line(raster, mid_x, mid_y); |
|---|
| 598 | gray_render_line(raster, to_x, to_y); |
|---|
| 599 | |
|---|
| 600 | top--; |
|---|
| 601 | arc -= 2; |
|---|
| 602 | } |
|---|
| 603 | } |
|---|
| 604 | return; |
|---|
| 605 | } |
|---|
| 606 | |
|---|
| 607 | static void gray_split_cubic(FT_Vector* base) |
|---|
| 608 | { |
|---|
| 609 | TPos a, b, c, d; |
|---|
| 610 | base[6].x = base[3].x; |
|---|
| 611 | c = base[1].x; |
|---|
| 612 | d = base[2].x; |
|---|
| 613 | base[1].x = a = (base[0].x + c) / 2; |
|---|
| 614 | base[5].x = b = (base[3].x + d) / 2; |
|---|
| 615 | c = (c + d) / 2; |
|---|
| 616 | base[2].x = a = (a + c) / 2; |
|---|
| 617 | base[4].x = b = (b + c) / 2; |
|---|
| 618 | base[3].x = (a + b) / 2; |
|---|
| 619 | base[6].y = base[3].y; |
|---|
| 620 | c = base[1].y; |
|---|
| 621 | d = base[2].y; |
|---|
| 622 | base[1].y = a = (base[0].y + c) / 2; |
|---|
| 623 | base[5].y = b = (base[3].y + d) / 2; |
|---|
| 624 | c = (c + d) / 2; |
|---|
| 625 | base[2].y = a = (a + c) / 2; |
|---|
| 626 | base[4].y = b = (b + c) / 2; |
|---|
| 627 | base[3].y = (a + b) / 2; |
|---|
| 628 | } |
|---|
| 629 | |
|---|
| 630 | static void gray_render_cubic(FT_Raster* raster, FT_Vector* control1, FT_Vector* control2, FT_Vector* to) |
|---|
| 631 | { |
|---|
| 632 | TPos dx, dy, da, db; |
|---|
| 633 | int top, level; |
|---|
| 634 | int* levels; |
|---|
| 635 | FT_Vector* arc; |
|---|
| 636 | |
|---|
| 637 | dx = DOWNSCALE(raster->x) + to->x -(control1->x << 1); |
|---|
| 638 | if (dx < 0) |
|---|
| 639 | dx = -dx; |
|---|
| 640 | dy = DOWNSCALE(raster->y) + to->y -(control1->y << 1); |
|---|
| 641 | if (dy < 0) |
|---|
| 642 | dy = -dy; |
|---|
| 643 | if (dx < dy) |
|---|
| 644 | dx = dy; |
|---|
| 645 | da = dx; |
|---|
| 646 | |
|---|
| 647 | dx = DOWNSCALE(raster->x) + to->x - 3 * (control1->x + control2->x); |
|---|
| 648 | if (dx < 0) |
|---|
| 649 | dx = -dx; |
|---|
| 650 | dy = DOWNSCALE(raster->y) + to->y - 3 * (control1->x + control2->y); |
|---|
| 651 | if (dy < 0) |
|---|
| 652 | dy = -dy; |
|---|
| 653 | if (dx < dy) |
|---|
| 654 | dx = dy; |
|---|
| 655 | db = dx; |
|---|
| 656 | |
|---|
| 657 | level = 1; |
|---|
| 658 | da = da / raster->cubic_level; |
|---|
| 659 | db = db / raster->conic_level; |
|---|
| 660 | while (da > 0 || db > 0) |
|---|
| 661 | { |
|---|
| 662 | da >>= 2; |
|---|
| 663 | db >>= 3; |
|---|
| 664 | level++; |
|---|
| 665 | } |
|---|
| 666 | |
|---|
| 667 | if (level <= 1) |
|---|
| 668 | { |
|---|
| 669 | TPos to_x, to_y, mid_x, mid_y; |
|---|
| 670 | |
|---|
| 671 | |
|---|
| 672 | to_x = UPSCALE(to->x); |
|---|
| 673 | to_y = UPSCALE(to->y); |
|---|
| 674 | mid_x = (raster->x + to_x + |
|---|
| 675 | 3 * UPSCALE(control1->x + control2->x)) / 8; |
|---|
| 676 | mid_y = (raster->y + to_y + |
|---|
| 677 | 3 * UPSCALE(control1->y + control2->y)) / 8; |
|---|
| 678 | |
|---|
| 679 | gray_render_line(raster, mid_x, mid_y); |
|---|
| 680 | gray_render_line(raster, to_x, to_y); |
|---|
| 681 | return; |
|---|
| 682 | } |
|---|
| 683 | |
|---|
| 684 | arc = raster->bez_stack; |
|---|
| 685 | arc[0].x = UPSCALE(to->x); |
|---|
| 686 | arc[0].y = UPSCALE(to->y); |
|---|
| 687 | arc[1].x = UPSCALE(control2->x); |
|---|
| 688 | arc[1].y = UPSCALE(control2->y); |
|---|
| 689 | arc[2].x = UPSCALE(control1->x); |
|---|
| 690 | arc[2].y = UPSCALE(control1->y); |
|---|
| 691 | arc[3].x = raster->x; |
|---|
| 692 | arc[3].y = raster->y; |
|---|
| 693 | |
|---|
| 694 | levels = raster->lev_stack; |
|---|
| 695 | top = 0; |
|---|
| 696 | levels[0] = level; |
|---|
| 697 | |
|---|
| 698 | while (top >= 0) |
|---|
| 699 | { |
|---|
| 700 | level = levels[top]; |
|---|
| 701 | if (level > 1) |
|---|
| 702 | { |
|---|
| 703 | /* check that the arc crosses the current band */ |
|---|
| 704 | TPos min, max, y; |
|---|
| 705 | |
|---|
| 706 | |
|---|
| 707 | min = max = arc[0].y; |
|---|
| 708 | y = arc[1].y; |
|---|
| 709 | if (y < min) min = y; |
|---|
| 710 | if (y > max) max = y; |
|---|
| 711 | y = arc[2].y; |
|---|
| 712 | if (y < min) min = y; |
|---|
| 713 | if (y > max) max = y; |
|---|
| 714 | y = arc[3].y; |
|---|
| 715 | if (y < min) min = y; |
|---|
| 716 | if (y > max) max = y; |
|---|
| 717 | if (TRUNC(min) >= raster->max_ey || TRUNC(max) < 0) |
|---|
| 718 | goto Draw; |
|---|
| 719 | gray_split_cubic(arc); |
|---|
| 720 | arc += 3; |
|---|
| 721 | top ++; |
|---|
| 722 | levels[top] = levels[top - 1] = level - 1; |
|---|
| 723 | continue; |
|---|
| 724 | } |
|---|
| 725 | |
|---|
| 726 | Draw: |
|---|
| 727 | { |
|---|
| 728 | TPos to_x, to_y, mid_x, mid_y; |
|---|
| 729 | |
|---|
| 730 | |
|---|
| 731 | to_x = arc[0].x; |
|---|
| 732 | to_y = arc[0].y; |
|---|
| 733 | mid_x = (raster->x + to_x + 3 * (arc[1].x + arc[2].x)) / 8; |
|---|
| 734 | mid_y = (raster->y + to_y + 3 * (arc[1].y + arc[2].y)) / 8; |
|---|
| 735 | |
|---|
| 736 | gray_render_line(raster, mid_x, mid_y); |
|---|
| 737 | gray_render_line(raster, to_x, to_y); |
|---|
| 738 | top --; |
|---|
| 739 | arc -= 3; |
|---|
| 740 | } |
|---|
| 741 | } |
|---|
| 742 | return; |
|---|
| 743 | } |
|---|
| 744 | |
|---|
| 745 | #define PACK(a) (((long)(a)->y << 16) +(a)->x) |
|---|
| 746 | #define LESS_THAN(a, b)(PACK(a) < PACK(b)) |
|---|
| 747 | #define SWAP_CELLS(a, b, temp) do { temp = * (a); * (a) = * (b); * (b) = temp; } while (0) |
|---|
| 748 | #define QSORT_THRESHOLD 9 |
|---|
| 749 | |
|---|
| 750 | static void gray_quick_sort(FT_Cell* cells, int count) |
|---|
| 751 | { |
|---|
| 752 | FT_Cell* stack[40]; /* should be enough ;-) */ |
|---|
| 753 | FT_Cell** top; /* top of stack */ |
|---|
| 754 | FT_Cell* base; |
|---|
| 755 | FT_Cell* limit; |
|---|
| 756 | FT_Cell temp; |
|---|
| 757 | |
|---|
| 758 | limit = cells + count; |
|---|
| 759 | base = cells; |
|---|
| 760 | top = stack; |
|---|
| 761 | |
|---|
| 762 | for (;;) |
|---|
| 763 | { |
|---|
| 764 | int len = (int)(limit - base); |
|---|
| 765 | FT_Cell* i; |
|---|
| 766 | FT_Cell* j; |
|---|
| 767 | FT_Cell* pivot; |
|---|
| 768 | |
|---|
| 769 | |
|---|
| 770 | if (len > QSORT_THRESHOLD) |
|---|
| 771 | { |
|---|
| 772 | /* we use base + len/2 as the pivot */ |
|---|
| 773 | pivot = base + len / 2; |
|---|
| 774 | SWAP_CELLS(base, pivot, temp); |
|---|
| 775 | |
|---|
| 776 | i = base + 1; |
|---|
| 777 | j = limit - 1; |
|---|
| 778 | |
|---|
| 779 | /* now ensure that *i <= *base <= *j */ |
|---|
| 780 | if (LESS_THAN(j, i)) |
|---|
| 781 | SWAP_CELLS(i, j, temp); |
|---|
| 782 | |
|---|
| 783 | if (LESS_THAN(base, i)) |
|---|
| 784 | SWAP_CELLS(base, i, temp); |
|---|
| 785 | |
|---|
| 786 | if (LESS_THAN(j, base)) |
|---|
| 787 | SWAP_CELLS(base, j, temp); |
|---|
| 788 | |
|---|
| 789 | for (;;) |
|---|
| 790 | { |
|---|
| 791 | do i++; while (LESS_THAN(i, base)); |
|---|
| 792 | do j--; while (LESS_THAN(base, j)); |
|---|
| 793 | |
|---|
| 794 | if (i > j) |
|---|
| 795 | break; |
|---|
| 796 | |
|---|
| 797 | SWAP_CELLS(i, j, temp); |
|---|
| 798 | } |
|---|
| 799 | |
|---|
| 800 | SWAP_CELLS(base, j, temp); |
|---|
| 801 | |
|---|
| 802 | /* now, push the largest sub-array */ |
|---|
| 803 | if (j - base > limit - i) |
|---|
| 804 | { |
|---|
| 805 | top[0] = base; |
|---|
| 806 | top[1] = j; |
|---|
| 807 | base = i; |
|---|
| 808 | } |
|---|
| 809 | else |
|---|
| 810 | { |
|---|
| 811 | top[0] = i; |
|---|
| 812 | top[1] = limit; |
|---|
| 813 | limit = j; |
|---|
| 814 | } |
|---|
| 815 | top += 2; |
|---|
| 816 | } |
|---|
| 817 | else |
|---|
| 818 | { |
|---|
| 819 | /* the sub-array is small, perform insertion sort */ |
|---|
| 820 | j = base; |
|---|
| 821 | i = j + 1; |
|---|
| 822 | |
|---|
| 823 | for (; i < limit; j = i, i++) |
|---|
| 824 | { |
|---|
| 825 | for (; LESS_THAN(j + 1, j); j--) |
|---|
| 826 | { |
|---|
| 827 | SWAP_CELLS(j + 1, j, temp); |
|---|
| 828 | if (j == base) |
|---|
| 829 | break; |
|---|
| 830 | } |
|---|
| 831 | } |
|---|
| 832 | if (top > stack) |
|---|
| 833 | { |
|---|
| 834 | top -= 2; |
|---|
| 835 | base = top[0]; |
|---|
| 836 | limit = top[1]; |
|---|
| 837 | } |
|---|
| 838 | else |
|---|
| 839 | break; |
|---|
| 840 | } |
|---|
| 841 | } |
|---|
| 842 | } |
|---|
| 843 | |
|---|
| 844 | static void FT_Outline_Translate(FT_Outline* outline, FT_Pos xOffset, FT_Pos yOffset) |
|---|
| 845 | { |
|---|
| 846 | int n; |
|---|
| 847 | FT_Vector* vec = outline->points; |
|---|
| 848 | for (n = 0; n < outline->nPoint; n++) |
|---|
| 849 | { |
|---|
| 850 | vec->x += xOffset; |
|---|
| 851 | vec->y += yOffset; |
|---|
| 852 | vec++; |
|---|
| 853 | } |
|---|
| 854 | } |
|---|
| 855 | |
|---|
| 856 | static void gray_render_span(int y, int count, FT_Span* spans, FT_Raster* raster) |
|---|
| 857 | { |
|---|
| 858 | unsigned char* p; |
|---|
| 859 | FT_Bitmap* map = &raster->bitmap; |
|---|
| 860 | _SF((dbg_fp, "gray_render_span(y=%d, count=%d)", y, count)); |
|---|
| 861 | p = (unsigned char*)map->buffer_ - y * map->pitch; |
|---|
| 862 | if (map->pitch >= 0) p += (map->rows - 1) * map->pitch; |
|---|
| 863 | for (; count > 0; count--, spans++) |
|---|
| 864 | { |
|---|
| 865 | if (spans->coverage) |
|---|
| 866 | { |
|---|
| 867 | _OO((dbg_fp, "spans->x=%d, spans->len=%d, spans->coverage=%d", spans->x, spans->len, spans->coverage)); |
|---|
| 868 | memset(p+spans->x, spans->coverage, spans->len); |
|---|
| 869 | } |
|---|
| 870 | } |
|---|
| 871 | _EF((dbg_fp, "gray_render_span()")); |
|---|
| 872 | } |
|---|
| 873 | |
|---|
| 874 | static void gray_hline(FT_Raster* raster, TCoord x, TCoord y, TPos area, int acount) |
|---|
| 875 | { |
|---|
| 876 | FT_Span* span; |
|---|
| 877 | int count; |
|---|
| 878 | int coverage; |
|---|
| 879 | _SF((dbg_fp, "gray_hline(x=%d, y=%d, area=%d, acount=%d)", x, y, area, acount)); |
|---|
| 880 | coverage = (int)(area >>(PIXEL_BITS * 2 + 1 - 8)); |
|---|
| 881 | _OO((dbg_fp, "coverage=%d", coverage)); |
|---|
| 882 | if (coverage < 0) coverage = -coverage; |
|---|
| 883 | if (coverage >= 256) coverage = 255; |
|---|
| 884 | y += (TCoord)raster->min_ey; |
|---|
| 885 | x += (TCoord)raster->min_ex; |
|---|
| 886 | _OO((dbg_fp, "coverage=%d, x=%d, y=%d", coverage, x, y)); |
|---|
| 887 | if (coverage) |
|---|
| 888 | { |
|---|
| 889 | _OO((dbg_fp, "if (coverage)")); |
|---|
| 890 | _TI(); |
|---|
| 891 | count = raster->num_gray_spans; |
|---|
| 892 | span = raster->gray_spans + count - 1; |
|---|
| 893 | _OO((dbg_fp, "raster->num_gray_spans=%d, span[%d]", count, span-raster->gray_spans)); |
|---|
| 894 | if (count > 0 && raster->span_y == y && (int)span->x + span->len == (int)x && span->coverage == coverage) |
|---|
| 895 | { |
|---|
| 896 | _OO((dbg_fp, "if (count > 0 && raster->span_y == y && (int)span->x + span->len == (int)x && span->coverage == coverage)")); |
|---|
| 897 | _TI(); |
|---|
| 898 | span->len = (unsigned short)(span->len + acount); |
|---|
| 899 | _OO((dbg_fp, "span->len=%d", span->len)); |
|---|
| 900 | _TD(); |
|---|
| 901 | _EF((dbg_fp, "gray_hline()")); |
|---|
| 902 | return; |
|---|
| 903 | } |
|---|
| 904 | if (raster->span_y != y || count >= FT_MAX_GRAY_SPANS) |
|---|
| 905 | { |
|---|
| 906 | _OO((dbg_fp, "if (raster->span_y != y || count >= FT_MAX_GRAY_SPANS)")); |
|---|
| 907 | _TI(); |
|---|
| 908 | if (count > 0) gray_render_span(raster->span_y, count, raster->gray_spans, raster); |
|---|
| 909 | raster->num_gray_spans = 0; |
|---|
| 910 | raster->span_y = y; |
|---|
| 911 | count = 0; |
|---|
| 912 | span = raster->gray_spans; |
|---|
| 913 | _OO((dbg_fp, "raster: num_gray_spans=%d, span_y=%d", raster->num_gray_spans, raster->span_y)); |
|---|
| 914 | _OO((dbg_fp, "count=0, span[%d]", span-raster->gray_spans)); |
|---|
| 915 | _TD(); |
|---|
| 916 | } |
|---|
| 917 | else span++; |
|---|
| 918 | span->x = (short)x; |
|---|
| 919 | span->len = (unsigned short)acount; |
|---|
| 920 | span->coverage = (unsigned char)coverage; |
|---|
| 921 | raster->num_gray_spans++; |
|---|
| 922 | _OO((dbg_fp, "span[%d]: x=%d, len=%d, coverage=%d", span-raster->gray_spans, span->x, span->len, span->coverage)); |
|---|
| 923 | _TD(); |
|---|
| 924 | } |
|---|
| 925 | _EF((dbg_fp, "gray_hline()")); |
|---|
| 926 | } |
|---|
| 927 | |
|---|
| 928 | static void gray_sweep(FT_Raster* raster, FT_Bitmap* bitmap) |
|---|
| 929 | { |
|---|
| 930 | TCoord x, y, cover; |
|---|
| 931 | TArea area; |
|---|
| 932 | FT_Cell* start; |
|---|
| 933 | FT_Cell* limit; |
|---|
| 934 | FT_Cell* cur; |
|---|
| 935 | if (raster->num_cells == 0) return; |
|---|
| 936 | _SF((dbg_fp, "gray_sweep()")); |
|---|
| 937 | cur = raster->cells; |
|---|
| 938 | limit = cur + raster->num_cells; |
|---|
| 939 | cover = 0; |
|---|
| 940 | raster->span_y = -1; |
|---|
| 941 | raster->num_gray_spans = 0; |
|---|
| 942 | _OO((dbg_fp, "limit=%d, cover=%d", limit, cover)); |
|---|
| 943 | _OO((dbg_fp, "raster: limit=%d, num_gray_spans=%d", raster->span_y, raster->num_gray_spans)); |
|---|
| 944 | _TI(); |
|---|
| 945 | for (;;) |
|---|
| 946 | { |
|---|
| 947 | start = cur; |
|---|
| 948 | y = start->y; |
|---|
| 949 | x = start->x; |
|---|
| 950 | area = start->area; |
|---|
| 951 | cover += start->cover; |
|---|
| 952 | _OO((dbg_fp, "start=%d, x=%d, y=%d, area=%d, cover=%d", start-raster->cells, x, y, area, cover)); |
|---|
| 953 | _TI(); |
|---|
| 954 | for (;;) |
|---|
| 955 | { |
|---|
| 956 | ++cur; |
|---|
| 957 | if (cur >= limit || cur->y != start->y || cur->x != start->x) break; |
|---|
| 958 | area += cur->area; |
|---|
| 959 | cover += cur->cover; |
|---|
| 960 | _OO((dbg_fp, "cur=%d, area=%d, cover=%d", cur-raster->cells, area, cover)); |
|---|
| 961 | } |
|---|
| 962 | if (area && x >= 0) |
|---|
| 963 | { |
|---|
| 964 | _OO((dbg_fp, "if (area && x >= 0)")); |
|---|
| 965 | _TI(); |
|---|
| 966 | gray_hline(raster, x, y, cover * (ONE_PIXEL * 2) - area, 1); |
|---|
| 967 | x++; |
|---|
| 968 | _TD(); |
|---|
| 969 | } |
|---|
| 970 | if (x < 0) x = 0; |
|---|
| 971 | if (cur < limit && start->y == cur->y) |
|---|
| 972 | { |
|---|
| 973 | _OO((dbg_fp, "if (cur < limit && start->y == cur->y)")); |
|---|
| 974 | _TI(); |
|---|
| 975 | if (cur->x > x) gray_hline(raster, x, y, cover * (ONE_PIXEL * 2), cur->x - x); |
|---|
| 976 | _TD(); |
|---|
| 977 | } |
|---|
| 978 | else |
|---|
| 979 | { |
|---|
| 980 | _OO((dbg_fp, "else")); |
|---|
| 981 | _TI(); |
|---|
| 982 | if (cover && x < raster->max_ex - raster->min_ex) gray_hline(raster, x, y, cover * (ONE_PIXEL * 2), (int)(raster->max_ex - x - raster->min_ex)); |
|---|
| 983 | cover = 0; |
|---|
| 984 | _TD(); |
|---|
| 985 | } |
|---|
| 986 | _TD(); |
|---|
| 987 | if (cur >= limit) break; |
|---|
| 988 | } |
|---|
| 989 | _TD(); |
|---|
| 990 | if (raster->num_gray_spans > 0) gray_render_span(raster->span_y, raster->num_gray_spans, raster->gray_spans, raster); |
|---|
| 991 | _EF((dbg_fp, "gray_sweep()")); |
|---|
| 992 | } |
|---|
| 993 | |
|---|
| 994 | static void gray_move_to(FT_Vector* to, FT_Raster* raster) |
|---|
| 995 | { |
|---|
| 996 | TPos x, y; |
|---|
| 997 | _SF((dbg_fp, "gray_move_to()")); |
|---|
| 998 | gray_record_cell(raster); |
|---|
| 999 | x = UPSCALE(to->x); |
|---|
| 1000 | y = UPSCALE(to->y); |
|---|
| 1001 | gray_start_cell(raster, TRUNC(x), TRUNC(y)); |
|---|
| 1002 | raster->x = x; |
|---|
| 1003 | raster->y = y; |
|---|
| 1004 | _EF((dbg_fp, "gray_move_to()")); |
|---|
| 1005 | } |
|---|
| 1006 | |
|---|
| 1007 | static int gray_raster_render(FT_Raster* raster) |
|---|
| 1008 | { |
|---|
| 1009 | FT_Outline* outline = &raster->outline; |
|---|
| 1010 | FT_Bitmap* bitmap = &raster->bitmap; |
|---|
| 1011 | FT_Vector v_last; |
|---|
| 1012 | FT_Vector v_control; |
|---|
| 1013 | FT_Vector v_start; |
|---|
| 1014 | FT_Vector* point; |
|---|
| 1015 | FT_Vector* limit; |
|---|
| 1016 | char* on; |
|---|
| 1017 | FT_Int n; /* index of contour in outline */ |
|---|
| 1018 | FT_UInt first = 0; /* index of first point in contour */ |
|---|
| 1019 | FT_Int tag; /* current point's state */ |
|---|
| 1020 | _SF((dbg_fp, "gray_raster_render()")); |
|---|
| 1021 | gray_compute_cbox(raster); |
|---|
| 1022 | raster->num_cells = 0; |
|---|
| 1023 | raster->invalid = 1; |
|---|
| 1024 | raster->conic_level = 32; |
|---|
| 1025 | raster->cubic_level = 16; |
|---|
| 1026 | if (raster->max_ex > 24 || raster->max_ey > 24) |
|---|
| 1027 | { |
|---|
| 1028 | raster->conic_level <<= 1; |
|---|
| 1029 | raster->cubic_level <<= 1; |
|---|
| 1030 | } |
|---|
| 1031 | for (n = 0; n < outline->nPath; n++) |
|---|
| 1032 | { |
|---|
| 1033 | FT_Int last; /* index of last point in contour */ |
|---|
| 1034 | last = outline->endPointIndex[n]; |
|---|
| 1035 | limit = outline->points + last; |
|---|
| 1036 | v_start = outline->points[first]; |
|---|
| 1037 | v_last = outline->points[last]; |
|---|
| 1038 | v_control = v_start; |
|---|
| 1039 | point = outline->points + first; |
|---|
| 1040 | on = outline->on + first; |
|---|
| 1041 | tag = FT_CURVE_TAG(on[0]); |
|---|
| 1042 | if (tag == FT_CURVE_TAG_CONIC) |
|---|
| 1043 | { |
|---|
| 1044 | /* first point is conic control. Yes, this happens. */ |
|---|
| 1045 | if (FT_CURVE_TAG(outline->on[last]) == FT_CURVE_TAG_ON) |
|---|
| 1046 | { |
|---|
| 1047 | /* start at last point if it is on the curve */ |
|---|
| 1048 | v_start = v_last; |
|---|
| 1049 | limit--; |
|---|
| 1050 | } |
|---|
| 1051 | else |
|---|
| 1052 | { |
|---|
| 1053 | /* if both first and last points are conic, */ |
|---|
| 1054 | /* start at their middle and record its position */ |
|---|
| 1055 | /* for closure */ |
|---|
| 1056 | v_start.x = (v_start.x + v_last.x) / 2; |
|---|
| 1057 | v_start.y = (v_start.y + v_last.y) / 2; |
|---|
| 1058 | v_last = v_start; |
|---|
| 1059 | } |
|---|
| 1060 | point--; |
|---|
| 1061 | on--; |
|---|
| 1062 | } |
|---|
| 1063 | gray_move_to(&v_start, raster); |
|---|
| 1064 | while (point < limit) |
|---|
| 1065 | { |
|---|
| 1066 | point++; |
|---|
| 1067 | on++; |
|---|
| 1068 | tag = FT_CURVE_TAG(on[0]); |
|---|
| 1069 | switch (tag) |
|---|
| 1070 | { |
|---|
| 1071 | case FT_CURVE_TAG_ON: /* emit a single line_to */ |
|---|
| 1072 | { |
|---|
| 1073 | gray_render_line(raster, UPSCALE(point->x), UPSCALE(point->y)); |
|---|
| 1074 | continue; |
|---|
| 1075 | } |
|---|
| 1076 | case FT_CURVE_TAG_CONIC: /* consume conic arcs */ |
|---|
| 1077 | v_control.x = point->x; |
|---|
| 1078 | v_control.y = point->y; |
|---|
| 1079 | Do_Conic: |
|---|
| 1080 | if (point < limit) |
|---|
| 1081 | { |
|---|
| 1082 | FT_Vector vec; |
|---|
| 1083 | FT_Vector v_middle; |
|---|
| 1084 | point++; |
|---|
| 1085 | on++; |
|---|
| 1086 | tag = FT_CURVE_TAG(on[0]); |
|---|
| 1087 | vec.x = point->x; |
|---|
| 1088 | vec.y = point->y; |
|---|
| 1089 | if (tag == FT_CURVE_TAG_ON) |
|---|
| 1090 | { |
|---|
| 1091 | gray_render_conic(raster, &v_control, &vec); |
|---|
| 1092 | continue; |
|---|
| 1093 | } |
|---|
| 1094 | v_middle.x = (v_control.x + vec.x) / 2; |
|---|
| 1095 | v_middle.y = (v_control.y + vec.y) / 2; |
|---|
| 1096 | gray_render_conic(raster, &v_control, &v_middle); |
|---|
| 1097 | v_control = vec; |
|---|
| 1098 | goto Do_Conic; |
|---|
| 1099 | } |
|---|
| 1100 | gray_render_conic(raster, &v_control, &v_start); |
|---|
| 1101 | goto Close; |
|---|
| 1102 | default: /* FT_CURVE_TAG_CUBIC */ |
|---|
| 1103 | { |
|---|
| 1104 | FT_Vector vec1, vec2; |
|---|
| 1105 | point += 2; |
|---|
| 1106 | on += 2; |
|---|
| 1107 | vec1.x = point[-2].x; vec1.y = point[-2].y; |
|---|
| 1108 | vec2.x = point[-1].x; vec2.y = point[-1].y; |
|---|
| 1109 | if (point <= limit) |
|---|
| 1110 | { |
|---|
| 1111 | FT_Vector vec; |
|---|
| 1112 | vec.x = point->x; |
|---|
| 1113 | vec.y = point->y; |
|---|
| 1114 | gray_render_cubic(raster, &vec1, &vec2, &vec); |
|---|
| 1115 | continue; |
|---|
| 1116 | } |
|---|
| 1117 | gray_render_cubic(raster, &vec1, &vec2, &v_start); |
|---|
| 1118 | goto Close; |
|---|
| 1119 | } |
|---|
| 1120 | } |
|---|
| 1121 | } |
|---|
| 1122 | /* close the contour with a line segment */ |
|---|
| 1123 | gray_render_line(raster, UPSCALE(v_start.x), UPSCALE(v_start.y)); |
|---|
| 1124 | Close: first = last + 1; |
|---|
| 1125 | } |
|---|
| 1126 | gray_record_cell(raster); |
|---|
| 1127 | gray_quick_sort(raster->cells, raster->num_cells); |
|---|
| 1128 | gray_sweep(raster, &raster->bitmap); |
|---|
| 1129 | _EF((dbg_fp, "gray_raster_render()")); |
|---|
| 1130 | return 0; |
|---|
| 1131 | } |
|---|
| 1132 | |
|---|
| 1133 | static char pool_base[0x100000]; |
|---|
| 1134 | static FT_Raster raster; |
|---|
| 1135 | |
|---|
| 1136 | void ut_SubpixelScale(UT_FONT_TASK* task, UT_IMAGE* image) |
|---|
| 1137 | { |
|---|
| 1138 | int i; |
|---|
| 1139 | gray_init_cells(&raster, pool_base, sizeof(pool_base)); |
|---|
| 1140 | |
|---|
| 1141 | ut_AllocScanBuffer(task, image, image->lSize); |
|---|
| 1142 | raster.bitmap.buffer_ = image->data; |
|---|
| 1143 | raster.bitmap.width = image->bbox.sx; |
|---|
| 1144 | raster.bitmap.rows = image->bbox.sy; |
|---|
| 1145 | raster.bitmap.pitch = image->bSize; |
|---|
| 1146 | memset(image->data, 0, image->lSize); |
|---|
| 1147 | |
|---|
| 1148 | raster.outline.nPath = task->rootGlyph.nPath; |
|---|
| 1149 | raster.outline.nPoint = task->rootGlyph.nPoint; |
|---|
| 1150 | raster.outline.on = task->rootGlyph.on; |
|---|
| 1151 | raster.outline.endPointIndex = task->rootGlyph.endPointIndex; |
|---|
| 1152 | for (i=0; i<task->rootGlyph.nPoint; i++) |
|---|
| 1153 | { |
|---|
| 1154 | raster.outline.points[i].x = task->rootGlyph.x[i] / 8; |
|---|
| 1155 | raster.outline.points[i].y = task->rootGlyph.y[i] / 8; |
|---|
| 1156 | raster.outline.on[i] = 1; |
|---|
| 1157 | } |
|---|
| 1158 | gray_raster_render(&raster); |
|---|
| 1159 | } |
|---|