[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
feature/android 795f5a16b5 1/4: Update Android port
From: |
Po Lu |
Subject: |
feature/android 795f5a16b5 1/4: Update Android port |
Date: |
Tue, 7 Feb 2023 10:11:10 -0500 (EST) |
branch: feature/android
commit 795f5a16b56a757fbb77562f47aaa4513ca52dbc
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>
Update Android port
* INSTALL.android: Describe patches for BoringSSL on ARM.
* src/sfnt.c (sfnt_build_glyph_outline): Remove redundant
multiplication.
(sfnt_prepare_raster): Update offset calculation for changes.
(sfnt_step_edge, sfnt_step_edge_n): Handle bresenham terms.
(sfnt_build_outline_edges): Don't subtract floored xmin, just
xmin.
(sfnt_saturate_short): Make clang generate better code.
(sfnt_fill_span): Stop rounding coordinates.
(sfnt_poly_span): Poly consecutive on transitions all in one go.
(sfnt_lookup_glyph_metrics): Remove redundant multiplication.
(struct sfnt_interpreter): New hooks for debugging.
(sfnt_large_integer_add): New function.
(sfnt_mul_f26dot6_fixed): Round product.
(sfnt_make_interpreter): Remove redundant multiplication.
(CHECK_STACK_ELEMENTS, POP_UNCHECKED, PUSH_UNCHECKED): New
macros.
(MOVE, POP, SWAP, CINDEX, RS, RCVT, LT, LTEQ, GT, GTEQ, EQ, NEQ)
(EVEN, AND, OR, NOT, ADD, SUB, DIV, MUL, ABS, NEG, FLOOR, CEILING)
(GETINFO, ROLL, _MAX, _MIN, ROUND, NROUND, GC, MD): Don't check
SP redundantly, especially when pushing an element right after
popping one.
(sfnt_move_glyph_zone): Don't touch points by passing NULL as
flags.
(sfnt_direct_move_zp2): Touch P in the directions of the
movement.
(sfnt_interpret_scfs): Fix coding style.
(sfnt_interpret_simple_glyph): Don't round Y coordinates.
(sfnt_test_span, sfnt_test_edges, sfnt_debug_edges, sfnt_test_edge)
(sfnt_x_raster, sfnt_test_raster, rcvt_test_args)
(deltac1_test_args, deltac2_test_args, deltac3_test_args)
(roll_1_test_args, sfnt_run_hook, sfnt_identify_instruction)
(sfnt_verbose, main): Improve debug code and tests.
* src/sfnt.h (struct sfnt_edge): Add bresenham terms.
---
INSTALL.android | 72 ++++++
src/sfnt.c | 769 +++++++++++++++++++++++++++++++++++++++++++++-----------
src/sfnt.h | 21 +-
3 files changed, 711 insertions(+), 151 deletions(-)
diff --git a/INSTALL.android b/INSTALL.android
index 6366b8d664..a8d7333149 100644
--- a/INSTALL.android
+++ b/INSTALL.android
@@ -178,6 +178,8 @@ work, along with what has to be patched to make them work:
https://android.googlesource.com/platform/system/core/+/refs/heads/nougat-mr1-dev/libpackagelistparser/
libpcre - https://android.googlesource.com/platform/external/pcre
libcrypto - https://android.googlesource.com/platform/external/boringssl
+ (You must apply the patch at the end of this file when building for
+ ARM systems.)
Many of these dependencies have been migrated over to the
``Android.bp'' build system now used to build Android itself.
@@ -650,6 +652,20 @@ index bf277d2..36734d9 100644
LOCAL_SDK_VERSION := 23
include $(BUILD_STATIC_LIBRARY)
+diff --git a/dist/sqlite3.c b/dist/sqlite3.c
+index b0536a4..8fa1ee9 100644
+--- a/dist/sqlite3.c
++++ b/dist/sqlite3.c
+@@ -26474,7 +26474,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
+ */
+ #if !defined(HAVE_POSIX_FALLOCATE) \
+ && (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L)
+-# define HAVE_POSIX_FALLOCATE 1
++/* # define HAVE_POSIX_FALLOCATE 1 */
+ #endif
+
+ /*
+
PATCH FOR WEBP
diff --git a/Android.mk b/Android.mk
@@ -733,3 +749,59 @@ index 5206a9f..b351ffc 100644
free(strp);
}
va_end(ap);
+
+PATCH FOR BORINGSSL
+
+diff --git a/Android.mk b/Android.mk
+index 3e3ef2a..277d4a9 100644
+--- a/Android.mk
++++ b/Android.mk
+@@ -27,7 +27,9 @@ LOCAL_MODULE := libcrypto
+ LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
+ LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
$(LOCAL_PATH)/crypto-sources.mk
+ LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY
-DBORINGSSL_IMPLEMENTATION -DOPENSSL_SMALL -Wno-unused-parameter
++LOCAL_CFLAGS_arm = -DOPENSSL_STATIC_ARMCAP -DOPENSSL_NO_ASM
+ LOCAL_SDK_VERSION := 9
++LOCAL_LDFLAGS = --no-undefined
+ # sha256-armv4.S does not compile with clang.
+ LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
+ LOCAL_CLANG_ASFLAGS_arm64 += -march=armv8-a+crypto
+diff --git a/sources.mk b/sources.mk
+index e82f3d5..be3a3c4 100644
+--- a/sources.mk
++++ b/sources.mk
+@@ -337,20 +337,20 @@ linux_aarch64_sources := \
+ linux-aarch64/crypto/sha/sha256-armv8.S\
+ linux-aarch64/crypto/sha/sha512-armv8.S\
+
+-linux_arm_sources := \
+- linux-arm/crypto/aes/aes-armv4.S\
+- linux-arm/crypto/aes/aesv8-armx32.S\
+- linux-arm/crypto/aes/bsaes-armv7.S\
+- linux-arm/crypto/bn/armv4-mont.S\
+- linux-arm/crypto/modes/ghash-armv4.S\
+- linux-arm/crypto/modes/ghashv8-armx32.S\
+- linux-arm/crypto/sha/sha1-armv4-large.S\
+- linux-arm/crypto/sha/sha256-armv4.S\
+- linux-arm/crypto/sha/sha512-armv4.S\
+- src/crypto/chacha/chacha_vec_arm.S\
+- src/crypto/cpu-arm-asm.S\
+- src/crypto/curve25519/asm/x25519-asm-arm.S\
+- src/crypto/poly1305/poly1305_arm_asm.S\
++# linux_arm_sources := \
++# linux-arm/crypto/aes/aes-armv4.S\
++# linux-arm/crypto/aes/aesv8-armx32.S\
++# linux-arm/crypto/aes/bsaes-armv7.S\
++# linux-arm/crypto/bn/armv4-mont.S\
++# linux-arm/crypto/modes/ghash-armv4.S\
++# linux-arm/crypto/modes/ghashv8-armx32.S\
++# linux-arm/crypto/sha/sha1-armv4-large.S\
++# linux-arm/crypto/sha/sha256-armv4.S\
++# linux-arm/crypto/sha/sha512-armv4.S\
++# src/crypto/chacha/chacha_vec_arm.S\
++# src/crypto/cpu-arm-asm.S\
++# src/crypto/curve25519/asm/x25519-asm-arm.S\
++# src/crypto/poly1305/poly1305_arm_asm.S\
+
+ linux_x86_sources := \
+ linux-x86/crypto/aes/aes-586.S\
diff --git a/src/sfnt.c b/src/sfnt.c
index 124185a507..13a73f057b 100644
--- a/src/sfnt.c
+++ b/src/sfnt.c
@@ -47,6 +47,7 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA. */
#include <errno.h>
#include <X11/Xlib.h>
+#include <X11/extensions/Xrender.h>
static void *
xmalloc (size_t size)
@@ -3489,8 +3490,7 @@ sfnt_build_glyph_outline (struct sfnt_glyph *glyph,
PIXEL = UNIT * PPEM / UPEM */
build_outline_context.factor
- = sfnt_div_fixed (pixel_size * 65536,
- head->units_per_em * 65536);
+ = sfnt_div_fixed (pixel_size, head->units_per_em);
/* Decompose the outline. */
rc = sfnt_decompose_glyph (glyph, sfnt_move_to_and_build,
@@ -3566,10 +3566,8 @@ sfnt_prepare_raster (struct sfnt_raster *raster,
+ (SFNT_POLY_ALIGNMENT - 1))
& ~(SFNT_POLY_ALIGNMENT - 1));
- raster->offx
- = sfnt_floor_fixed (outline->xmin) >> 16;
- raster->offy
- = sfnt_floor_fixed (outline->ymin) >> 16;
+ raster->offx = sfnt_round_fixed (outline->xmin) >> 16;
+ raster->offy = sfnt_floor_fixed (outline->ymin) >> 16;
}
typedef void (*sfnt_edge_proc) (struct sfnt_edge *, size_t,
@@ -3582,15 +3580,41 @@ typedef void (*sfnt_span_proc) (struct sfnt_edge *,
sfnt_fixed, void *);
static void
sfnt_step_edge (struct sfnt_edge *edge)
{
- /* Step edge. */
- edge->x += edge->step_x;
+ /* Add error accumulator. */
+ edge->error += edge->step_x;
+
+ while (edge->error > 0)
+ {
+ /* Subtract error and add 1. */
+ edge->x += edge->signed_step;
+ edge->error -= 65536;
+ }
}
-/* Build a list of edges for each contour in OUTLINE, applying
- OUTLINE->xmin and floor (OUTLINE->ymin) as the offset to each edge.
- Call EDGE_PROC with DCONTEXT and the resulting edges as arguments.
- It is OK to modify the edges given to EDGE_PROC. Align all edges
- to the sub-pixel grid. */
+/* Move EDGE->x forward, assuming that the scanline has moved upwards
+ by N, and that N is less than or equal to SFNT_POLY_STEP. */
+
+static void
+sfnt_step_edge_n (struct sfnt_edge *edge, sfnt_fixed n)
+{
+ /* Add error accumulator. */
+ edge->error += sfnt_mul_fixed (edge->step_x, n);
+
+ /* See if error is more than 0, and bring the line back to where it
+ should be. */
+
+ while (edge->error > 0)
+ {
+ /* Subtract error and add 1. */
+ edge->x += edge->signed_step;
+ edge->error -= 65536;
+ }
+}
+
+/* Build a list of edges for each contour in OUTLINE, applying xmin
+ and ymin as the offset to each edge. Call EDGE_PROC with DCONTEXT
+ and the resulting edges as arguments. It is OK to modify the edges
+ given to EDGE_PROC. Align all edges to the sub-pixel grid. */
static void
sfnt_build_outline_edges (struct sfnt_glyph_outline *outline,
@@ -3606,9 +3630,10 @@ sfnt_build_outline_edges (struct sfnt_glyph_outline
*outline,
edge = 0;
/* ymin and xmin must be the same as the offset used to set offy and
- offx in rasters. */
+ offx in rasters. However, xmin is not floored; otherwise, glyphs
+ like ``e'' look bad at certain ppem. */
ymin = sfnt_floor_fixed (outline->ymin);
- xmin = sfnt_floor_fixed (outline->xmin);
+ xmin = outline->xmin;
for (i = 0; i < outline->outline_used; ++i)
{
@@ -3666,9 +3691,21 @@ sfnt_build_outline_edges (struct sfnt_glyph_outline
*outline,
dy = abs (outline->outline[top].y
- outline->outline[bottom].y);
-#ifdef TEST
- edges[edge].source_x = edges[edge].x;
-#endif
+ /* Step to first grid point. */
+ y = sfnt_poly_grid_ceil (bot);
+
+ /* If rounding would make the edge not cover any area, skip this
+ edge. */
+ if (y >= edges[edge].top)
+ continue;
+
+ /* Compute the slope error. This is how much X changes for each
+ increase in Y. */
+
+ if (dx >= 0)
+ step_x = sfnt_div_fixed (dx, dy);
+ else
+ step_x = sfnt_div_fixed (-dx, dy);
/* Compute the increment. This is which direction X moves in
for each increase in Y. */
@@ -3676,30 +3713,19 @@ sfnt_build_outline_edges (struct sfnt_glyph_outline
*outline,
if (dx >= 0)
inc_x = 1;
else
- {
- inc_x = -1;
- dx = -dx;
- }
+ inc_x = -1;
- /* Compute the step X. This is how much X changes for each
- increase in Y. */
- step_x = inc_x * sfnt_div_fixed (dx, dy);
+ edges[edge].signed_step = SFNT_POLY_STEP * inc_x;
+ edges[edge].next = NULL;
- /* Step to first grid point. */
- y = sfnt_poly_grid_ceil (bot);
+ /* Set the initial Bresenham terms. */
+ edges[edge].error = step_x - 65536;
+ edges[edge].step_x = step_x;
- /* If rounding would make the edge not cover any area, skip this
- edge. */
- if (y > edges[edge].top)
- continue;
+ sfnt_step_edge_n (&edges[edge], bot - y);
- edges[edge].x += sfnt_mul_fixed (step_x, bot - y);
+ /* Set the bottom position. */
edges[edge].bottom = y;
- edges[edge].next = NULL;
-
- /* Compute the step X scaled to the poly step. */
- edges[edge].step_x
- = sfnt_mul_fixed (step_x, SFNT_POLY_STEP);
edge++;
}
@@ -3741,7 +3767,16 @@ sfnt_compare_edges (const void *a, const void *b)
coordinates, and incrementing the Y axis by SFNT_POLY_STEP instead
of 1. SFNT_POLY_STEP is chosen to always keep Y aligned to a grid
placed such that there are always 1 << SFNT_POLY_SHIFT positions
- available for each integral pixel coordinate. */
+ available for each integral pixel coordinate.
+
+ Moving upwards is performed using Bresenham's algorithm. Prior to
+ an edge being created, a single slope error is computed. This is
+ how much X should increase for each increase in Y.
+
+ Upon each increase in Y, X initially does not move. Instead, the
+ ``slope error'' is accumulated; once it exceeds the sample size,
+ one sample is subtracted from the accumulator, and X is increased
+ by one step. */
static void
sfnt_poly_edges (struct sfnt_edge *edges, size_t size,
@@ -3822,13 +3857,16 @@ sfnt_poly_edges (struct sfnt_edge *edges, size_t size,
}
}
-/* Saturate-convert the given unsigned short value X to an unsigned
- char. */
+/* Saturate and convert the given unsigned short value X to an
+ unsigned char. */
static unsigned char
sfnt_saturate_short (unsigned short x)
{
- return (unsigned char) ((x) | (0 - ((x) >> 8)));
+ if (x > 255)
+ return 255;
+
+ return x;
}
/* Fill a single span of pixels between X0 and X1 at Y, a raster
@@ -3855,11 +3893,6 @@ sfnt_fill_span (struct sfnt_raster *raster, sfnt_fixed y,
if (x1 <= x0)
return;
- /* Round Y, X0 and X1. */
- y += SFNT_POLY_ROUND;
- x0 += SFNT_POLY_ROUND;
- x1 += SFNT_POLY_ROUND;
-
/* Figure out coverage based on Y axis fractional. */
coverage = sfnt_poly_coverage[(y >> (16 - SFNT_POLY_SHIFT))
& SFNT_POLY_MASK];
@@ -3882,11 +3915,11 @@ sfnt_fill_span (struct sfnt_raster *raster, sfnt_fixed
y,
#endif
start += left >> SFNT_POLY_SHIFT;
+ w = 0;
+
/* Compute coverage for first pixel, then poly. */
if (left & SFNT_POLY_MASK)
{
- w = 0;
-
/* Note that col is an index into the columns of the coverage
map, unlike row which indexes the raster. */
col = 0;
@@ -3941,24 +3974,47 @@ sfnt_poly_span (struct sfnt_edge *start, sfnt_fixed y,
{
struct sfnt_edge *edge;
int winding;
- sfnt_fixed x0;
+ sfnt_fixed x0, x1;
+
+ /* Pacify -Wmaybe-uninitialized; x1 and x0 are only used when edge
+ != start, at which point x0 has already been set. */
+ x0 = x1 = 0;
/* Generate the X axis coverage map. Then poly it onto RASTER.
winding on each edge determines the winding direction: when it is
- positive, winding is 1. When it is negative, winding is -1. */
+ positive, winding is 1. When it is negative, winding is -1.
+
+ Fill each consecutive stretch of spans that are inside the glyph;
+ otherwise, coverage will overlap for some spans, but not
+ others.
+
+ The spans must be terminated with an edge that causes an
+ off-transition, or some spans will not be filled. */
winding = 0;
for (edge = start; edge; edge = edge->next)
{
if (!winding)
- x0 = edge->x;
+ {
+ if (edge != start && x0 != x1)
+ /* Draw this section of spans that are on. */
+ sfnt_fill_span (raster, (raster->height << 16) - y,
+ x0, x1);
+
+ x0 = x1 = edge->x;
+ }
else
- sfnt_fill_span (raster, (raster->height << 16) - y,
- x0, edge->x);
+ x1 = edge->x;
winding += edge->winding;
}
+
+ /* Draw the last span following the last off-transition. */
+
+ if (!winding && edge != start && x0 != x1)
+ sfnt_fill_span (raster, (raster->height << 16) - y,
+ x0, x1);
}
@@ -4143,8 +4199,7 @@ sfnt_lookup_glyph_metrics (sfnt_glyph glyph, int
pixel_size,
}
/* Now scale lbearing and advance up to the pixel size. */
- factor = sfnt_div_fixed (pixel_size << 16,
- head->units_per_em << 16);
+ factor = sfnt_div_fixed (pixel_size, head->units_per_em);
/* Save them. */
metrics->lbearing = sfnt_mul_fixed (lbearing << 16, factor);
@@ -5148,6 +5203,14 @@ struct sfnt_interpreter
/* If non-NULL, function called before each instruction is
executed. */
void (*run_hook) (struct sfnt_interpreter *);
+
+ /* If non-NULL, function called before each stack element is
+ pushed. */
+ void (*push_hook) (struct sfnt_interpreter *, uint32_t);
+
+ /* If non-NULL, function called before each stack element is
+ popped. */
+ void (*pop_hook) (struct sfnt_interpreter *, uint32_t);
#endif
};
@@ -5239,8 +5302,28 @@ sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b)
#endif
}
+#ifndef INT64_MAX
+
+/* Add the specified unsigned 32-bit N to the large integer
+ INTEGER. */
+
+static void
+sfnt_large_integer_add (struct sfnt_large_integer *integer,
+ uint32_t n)
+{
+ struct sfnt_large_integer number;
+
+ number.low = integer->low + n;
+ number.high = integer->high + (number.low
+ < integer->low);
+
+ *integer = number;
+}
+
+#endif
+
/* Multiply the specified 26.6 fixed point number X by the specified
- 16.16 fixed point number Y.
+ 16.16 fixed point number Y with symmetric rounding.
The 26.6 fixed point number must fit inside -32768 to 32767.ffff.
Value is otherwise undefined. */
@@ -5248,10 +5331,44 @@ sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b)
static sfnt_f26dot6
sfnt_mul_f26dot6_fixed (sfnt_f26dot6 x, sfnt_fixed y)
{
- sfnt_fixed result;
+#ifdef INT64_MAX
+ uint64_t product;
+ int sign;
- result = sfnt_mul_fixed (y, x);
- return result;
+ sign = 1;
+
+ if (x < 0)
+ {
+ x = -x;
+ sign = -sign;
+ }
+
+ if (y < 0)
+ {
+ y = -y;
+ sign = -sign;
+ }
+
+ product = (uint64_t) y * (uint64_t) x;
+
+ /* This can be done quickly with int64_t. */
+ return ((int64_t) (product + 32676) / (int64_t) 65536) * sign;
+#else
+ struct sfnt_large_integer temp;
+ int sign;
+
+ sign = 1;
+
+ if (x < 0)
+ sign = -sign;
+
+ if (y < 0)
+ sign = -sign;
+
+ sfnt_multiply_divide_1 (abs (x), abs (y), &temp);
+ sfnt_large_integer_add (&temp, 32676);
+ return sfnt_multiply_divide_2 (&temp, 65536) * sign;
+#endif
}
/* Return the floor of the specified 26.6 fixed point value X. */
@@ -5411,6 +5528,8 @@ sfnt_make_interpreter (struct sfnt_maxp_table *maxp,
#ifdef TEST
interpreter->run_hook = NULL;
+ interpreter->push_hook = NULL;
+ interpreter->pop_hook = NULL;
#endif
/* Fill in pointers and default values. */
@@ -5461,8 +5580,7 @@ sfnt_make_interpreter (struct sfnt_maxp_table *maxp,
/* Now compute the scale. Then, scale up the control value table
values. */
interpreter->scale
- = sfnt_div_fixed (pixel_size * 64,
- head->units_per_em * 64);
+ = sfnt_div_fixed (pixel_size, head->units_per_em);
/* Set the PPEM. */
interpreter->ppem = pixel_size;
@@ -5537,6 +5655,13 @@ sfnt_interpret_trap (struct sfnt_interpreter
*interpreter,
#define MOVE(a, b, n) \
memmove (a, b, (n) * sizeof (uint32_t))
+#define CHECK_STACK_ELEMENTS(n) \
+ { \
+ if ((interpreter->SP \
+ - interpreter->stack) < n) \
+ TRAP ("stack underflow"); \
+ }
+
#define CHECK_PREP() \
if (!is_prep) \
TRAP ("instruction executed not valid" \
@@ -5555,26 +5680,88 @@ sfnt_interpret_trap (struct sfnt_interpreter
*interpreter,
/* Register, alu and logic instructions. */
+#ifndef TEST
+
#define POP() \
(interpreter->SP == interpreter->stack \
? (TRAP ("stack underflow"), 0) \
: (*(--interpreter->SP)))
+#define POP_UNCHECKED() (*(--interpreter->SP))
+
+#else
+
+#define POP() \
+ (interpreter->SP == interpreter->stack \
+ ? (TRAP ("stack underflow"), 0) \
+ : ({uint32_t _value; \
+ _value = *(--interpreter->SP); \
+ if (interpreter->pop_hook) \
+ interpreter->pop_hook (interpreter, \
+ _value); \
+ _value;}))
+
+#define POP_UNCHECKED() \
+ ({uint32_t _value; \
+ _value = *(--interpreter->SP); \
+ if (interpreter->pop_hook) \
+ interpreter->pop_hook (interpreter, \
+ _value); \
+ _value;})
+
+#endif
+
#define LOOK() \
(interpreter->SP == interpreter->stack \
? (TRAP ("stack underflow"), 0) \
: *(interpreter->SP - 1))
+#ifndef TEST
+
+#define PUSH(value) \
+ { \
+ if ((char *) (interpreter->SP + 1) \
+ > (char *) interpreter->twilight_x) \
+ TRAP ("stack overflow"); \
+ \
+ *interpreter->SP = (value); \
+ interpreter->SP++; \
+ }
+
+#define PUSH_UNCHECKED(value) \
+ { \
+ *interpreter->SP = (value); \
+ interpreter->SP++; \
+ }
+
+#else
+
#define PUSH(value) \
{ \
if ((char *) (interpreter->SP + 1) \
> (char *) interpreter->twilight_x) \
TRAP ("stack overflow"); \
\
+ if (interpreter->push_hook) \
+ interpreter->push_hook (interpreter, \
+ value); \
+ \
*interpreter->SP = value; \
interpreter->SP++; \
}
+#define PUSH_UNCHECKED(value) \
+ { \
+ if (interpreter->push_hook) \
+ interpreter->push_hook (interpreter, \
+ value); \
+ \
+ *interpreter->SP = value; \
+ interpreter->SP++; \
+ }
+
+#endif
+
#define PUSH2(high, low) \
{ \
PUSH ((int16_t) ((int8_t) high) << 8 \
@@ -5746,8 +5933,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
a = POP (); \
b = POP (); \
\
- PUSH (a); \
- PUSH (b); \
+ PUSH_UNCHECKED (a); \
+ PUSH_UNCHECKED (b); \
}
#define DEPTH() \
@@ -5768,7 +5955,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
if (index <= 0 || index > STACKSIZE ()) \
TRAP ("stack overflow"); \
\
- PUSH (*(interpreter->SP - index)); \
+ PUSH_UNCHECKED (*(interpreter->SP \
+ - index)); \
}
#define MINDEX() \
@@ -5934,14 +6122,15 @@ sfnt_interpret_trap (struct sfnt_interpreter
*interpreter,
#define RS() \
{ \
- uint32_t address; \
+ uint32_t address, value; \
\
address = POP (); \
\
if (address >= interpreter->storage_size) \
TRAP ("invalid RS"); \
\
- PUSH (interpreter->storage[address]); \
+ value = interpreter->storage[address]; \
+ PUSH_UNCHECKED (value); \
}
#define WCVTP() \
@@ -5969,7 +6158,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
TRAP ("out of bounds RCVT"); \
\
value = interpreter->cvt[location]; \
- PUSH (value); \
+ PUSH_UNCHECKED (value); \
}
#define MPPEM() \
@@ -6004,7 +6193,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
e2 = POP (); \
e1 = POP (); \
\
- PUSH (e1 < e2 ? 1 : 0); \
+ PUSH_UNCHECKED (e1 < e2 ? 1 : 0); \
}
#define LTEQ() \
@@ -6014,7 +6203,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
e2 = POP (); \
e1 = POP (); \
\
- PUSH (e1 <= e2 ? 1 : 0); \
+ PUSH_UNCHECKED (e1 <= e2 ? 1 : 0); \
}
#define GT() \
@@ -6024,7 +6213,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
e2 = POP (); \
e1 = POP (); \
\
- PUSH (e1 > e2 ? 1 : 0); \
+ PUSH_UNCHECKED (e1 > e2 ? 1 : 0); \
}
#define GTEQ() \
@@ -6034,7 +6223,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
e2 = POP (); \
e1 = POP (); \
\
- PUSH (e1 >= e2 ? 1 : 0); \
+ PUSH_UNCHECKED (e1 >= e2 ? 1 : 0); \
}
#define EQ() \
@@ -6044,7 +6233,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
e1 = POP (); \
e2 = POP (); \
\
- PUSH (e1 == e2 ? 1 : 0); \
+ PUSH_UNCHECKED (e1 == e2 ? 1 : 0); \
}
#define NEQ() \
@@ -6054,7 +6243,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
e1 = POP (); \
e2 = POP (); \
\
- PUSH (e1 != e2 ? 1 : 0); \
+ PUSH_UNCHECKED (e1 != e2 ? 1 : 0); \
}
#define ODD() \
@@ -6073,6 +6262,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
#define EVEN() \
{ \
sfnt_f26dot6 e1, result; \
+ uint32_t value; \
\
e1 = POP (); \
result = abs (e1); \
@@ -6080,7 +6270,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
result \
= interpreter->state.round (result, \
interpreter); \
- PUSH (((result & 127) == 64) ? 0 : 1); \
+ value = ((result & 127) == 64) ? 0 : 1; \
+ PUSH_UNCHECKED (value); \
}
#define IF() \
@@ -6104,7 +6295,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
e1 = POP (); \
e2 = POP (); \
\
- PUSH (e1 && e2 ? 1 : 0); \
+ PUSH_UNCHECKED (e1 && e2 ? 1 : 0); \
}
#define OR() \
@@ -6114,7 +6305,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
e1 = POP (); \
e2 = POP (); \
\
- PUSH (e1 || e2 ? 1 : 0); \
+ PUSH_UNCHECKED (e1 || e2 ? 1 : 0); \
}
#define NOT() \
@@ -6123,7 +6314,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
\
e1 = POP (); \
\
- PUSH (!e1 ? 1 : 0); \
+ PUSH_UNCHECKED (!e1 ? 1 : 0); \
}
#define SDB() \
@@ -6154,7 +6345,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
n1 = POP (); \
n2 = POP (); \
\
- PUSH (sfnt_add (n1, n2)); \
+ PUSH_UNCHECKED (sfnt_add (n1, n2)); \
}
#define SUB() \
@@ -6164,7 +6355,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
n2 = POP (); \
n1 = POP (); \
\
- PUSH (sfnt_sub (n1, n2)); \
+ PUSH_UNCHECKED (sfnt_sub (n1, n2)); \
}
#define DIV() \
@@ -6177,7 +6368,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
if (!n2) \
TRAP ("DIV by 0"); \
\
- PUSH (sfnt_div_f26dot6 (n1, n2)); \
+ PUSH_UNCHECKED (sfnt_div_f26dot6 (n1, n2)); \
}
#define MUL() \
@@ -6187,7 +6378,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
n2 = POP (); \
n1 = POP (); \
\
- PUSH (sfnt_mul_f26dot6 (n2, n1)); \
+ PUSH_UNCHECKED (sfnt_mul_f26dot6 (n2, n1)); \
}
#define ABS() \
@@ -6196,10 +6387,10 @@ sfnt_interpret_trap (struct sfnt_interpreter
*interpreter,
\
n = POP (); \
\
- if (n == INT_MIN) \
- PUSH (0) \
+ if (n == INT32_MIN) \
+ PUSH_UNCHECKED (0) \
else \
- PUSH (n < 0 ? -n : n) \
+ PUSH_UNCHECKED (n < 0 ? -n : n) \
}
#define NEG() \
@@ -6208,10 +6399,10 @@ sfnt_interpret_trap (struct sfnt_interpreter
*interpreter,
\
n = POP (); \
\
- if (n == INT_MIN) \
- PUSH (0) \
+ if (n == INT32_MIN) \
+ PUSH_UNCHECKED (0) \
else \
- PUSH (-n) \
+ PUSH_UNCHECKED (-n) \
}
#define FLOOR() \
@@ -6219,7 +6410,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
sfnt_f26dot6 n; \
\
n = POP (); \
- PUSH (sfnt_floor_f26dot6 (n)); \
+ PUSH_UNCHECKED (sfnt_floor_f26dot6 (n)); \
}
#define CEILING() \
@@ -6227,7 +6418,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
sfnt_f26dot6 n; \
\
n = POP (); \
- PUSH (sfnt_ceil_f26dot6 (n)); \
+ PUSH_UNCHECKED (sfnt_ceil_f26dot6 (n)); \
}
#define WCVTF() \
@@ -6306,9 +6497,9 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
selector = POP (); \
\
if (selector & 1) \
- PUSH (2) \
+ PUSH_UNCHECKED (2) \
else \
- PUSH (0) \
+ PUSH_UNCHECKED (0) \
}
#define IDEF() \
@@ -6324,13 +6515,15 @@ sfnt_interpret_trap (struct sfnt_interpreter
*interpreter,
{ \
uint32_t a, b, c; \
\
- a = POP (); \
- b = POP (); \
- c = POP (); \
+ CHECK_STACK_ELEMENTS (3); \
\
- PUSH (b); \
- PUSH (a); \
- PUSH (c); \
+ a = POP_UNCHECKED (); \
+ b = POP_UNCHECKED (); \
+ c = POP_UNCHECKED (); \
+ \
+ PUSH_UNCHECKED (b); \
+ PUSH_UNCHECKED (a); \
+ PUSH_UNCHECKED (c); \
}
#define _MAX() \
@@ -6340,7 +6533,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
e1 = POP (); \
e2 = POP (); \
\
- PUSH (MAX (e1, e2)); \
+ PUSH_UNCHECKED (MAX (e1, e2)); \
}
#define _MIN() \
@@ -6350,7 +6543,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
e1 = POP (); \
e2 = POP (); \
\
- PUSH (MIN (e1, e2)); \
+ PUSH_UNCHECKED (MIN (e1, e2)); \
}
#define SCANTYPE() \
@@ -6427,7 +6620,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
result \
= interpreter->state.round (result, \
interpreter); \
- PUSH (n < 0 ? -result : result); \
+ PUSH_UNCHECKED (n < 0 ? -result : result); \
}
#define NROUND() \
@@ -6435,7 +6628,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
sfnt_f26dot6 n; \
\
n = POP (); \
- PUSH (n); \
+ PUSH_UNCHECKED (n); \
}
#define ROFF() \
@@ -6904,7 +7097,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
else \
value = PROJECT (x, y); \
\
- PUSH (value); \
+ PUSH_UNCHECKED (value); \
}
#define SCFS() \
@@ -6923,14 +7116,14 @@ sfnt_interpret_trap (struct sfnt_interpreter
*interpreter,
uint32_t p1, p2; \
sfnt_f26dot6 distance; \
\
- p1 = POP (); \
p2 = POP (); \
+ p1 = POP (); \
\
distance \
= sfnt_measure_distance (interpreter, \
p1, p2, \
opcode); \
- PUSH (distance); \
+ PUSH_UNCHECKED (distance); \
}
#define FLIPPT() \
@@ -7405,6 +7598,8 @@ sfnt_move_zp2 (struct sfnt_interpreter *interpreter,
uint32_t point,
/* Move N points from the specified POINT in INTERPRETER's glyph zone
by the given DISTANCE along the freedom vector.
+ Do not touch the points that are moved.
+
No checking is done to ensure that POINT lies inside the zone, or
even that the zone exists at all. */
@@ -7414,13 +7609,14 @@ sfnt_move_glyph_zone (struct sfnt_interpreter
*interpreter, uint32_t point,
{
interpreter->state.move (&interpreter->glyph_zone->x_current[point],
&interpreter->glyph_zone->y_current[point],
- n, interpreter, distance,
- &interpreter->glyph_zone->flags[point]);
+ n, interpreter, distance, NULL);
}
/* Move N points from the specified POINT in INTERPRETER's twilight
zone by the given DISTANCE along the freedom vector.
+ Do not touch the points that are moved.
+
No checking is done to ensure that POINT lies inside the zone, or
even that the zone exists at all. */
@@ -7436,6 +7632,8 @@ sfnt_move_twilight_zone (struct sfnt_interpreter
*interpreter, uint32_t point,
/* Move the point P in the zone pointed to by the ZP2 register in
INTERPRETER's graphics state by DX, and DY.
+ Touch the point P in the directions of the movement.
+
Check that P is valid; if not, trap. Else, perform the move
directly without converting it from the projection vector or to the
freedom vector. */
@@ -7464,6 +7662,12 @@ sfnt_direct_move_zp2 (struct sfnt_interpreter
*interpreter, uint32_t p,
= sfnt_add (interpreter->glyph_zone->x_current[p], dx);
interpreter->glyph_zone->y_current[p]
= sfnt_add (interpreter->glyph_zone->y_current[p], dy);
+
+ if (dx)
+ interpreter->glyph_zone->flags[p] |= SFNT_POINT_TOUCHED_X;
+
+ if (dy)
+ interpreter->glyph_zone->flags[p] |= SFNT_POINT_TOUCHED_Y;
}
}
@@ -7578,10 +7782,8 @@ sfnt_interpret_scfs (struct sfnt_interpreter
*interpreter,
if (!interpreter->state.zp2)
{
- interpreter->twilight_original_x[p]
- = interpreter->twilight_x[p];
- interpreter->twilight_original_y[p]
- = interpreter->twilight_y[p];
+ interpreter->twilight_original_x[p] = interpreter->twilight_x[p];
+ interpreter->twilight_original_y[p] = interpreter->twilight_y[p];
}
}
@@ -10974,8 +11176,9 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
/* Load the fword. */
tem = glyph->simple->y_coordinates[i];
- /* Scale that fword. */
- tem = sfnt_mul_f26dot6_fixed (tem * 64, interpreter->scale);
+ /* Scale that fword. Make sure not to round Y, as this could
+ lead to Y spilling over to the next line. */
+ tem = sfnt_mul_fixed (tem * 64, interpreter->scale);
/* Set y_points and y_current. */
zone->y_points[i] = tem;
@@ -11124,19 +11327,20 @@ static void
sfnt_test_span (struct sfnt_edge *edge, sfnt_fixed y,
void *dcontext)
{
-#if 0
+#if 1
printf ("/* span at %g */\n", sfnt_coerce_fixed (y));
for (; edge; edge = edge->next)
{
if (y >= edge->bottom && y < edge->top)
printf ("ctx.fillRect (%g, %g, 1, 1); "
- "/* %g top: %g bot: %g stepx: %g */\n",
+ "/* %g top: %g bot: %g stepx: %g winding: %d */\n",
sfnt_coerce_fixed (edge->x),
sfnt_coerce_fixed (sfnt_test_max - y),
sfnt_coerce_fixed (y),
sfnt_coerce_fixed (edge->bottom),
sfnt_coerce_fixed (edge->top),
- sfnt_coerce_fixed (edge->step_x));
+ sfnt_coerce_fixed (edge->step_x),
+ edge->winding);
}
#elif 0
int winding;
@@ -11171,6 +11375,74 @@ sfnt_test_edge_ignore (struct sfnt_edge *edges, size_t
num_edges,
}
+/* The same debugger stuff is used here. */
+static void sfnt_setup_debugger (void);
+
+/* The debugger's X display. */
+static Display *display;
+
+/* The debugger window. */
+static Window window;
+
+/* The GC. */
+static GC point_gc, background_gc;
+
+static void
+sfnt_test_edges (struct sfnt_edge *edges, size_t num_edges)
+{
+ static sfnt_fixed y;
+ size_t i;
+
+ for (i = 0; i < num_edges; ++i)
+ {
+ if (y >= edges[i].bottom && y < edges[i].top)
+ {
+ XDrawPoint (display, window, point_gc,
+ edges[i].x / 65536, 100 - (y / 65536));
+ printf ("sfnt_test_edges: %d %d\n",
+ edges[i].x / 65536, 100 - (y / 65536));
+ }
+ }
+
+ y += SFNT_POLY_STEP;
+
+ for (i = 0; i < num_edges; ++i)
+ sfnt_step_edge (&edges[i]);
+}
+
+static void
+sfnt_debug_edges (struct sfnt_edge *edges, size_t num_edges)
+{
+ XEvent event;
+
+ sfnt_setup_debugger ();
+
+ while (true)
+ {
+ XNextEvent (display, &event);
+
+ switch (event.type)
+ {
+ case KeyPress:
+ XDestroyWindow (display, window);
+ XCloseDisplay (display);
+ exit (0);
+ break;
+
+ case Expose:
+
+ while (true)
+ {
+ sfnt_test_edges (edges, num_edges);
+ XFlush (display);
+ usleep (50000);
+ }
+
+ break;
+ }
+ }
+}
+
static void
sfnt_test_edge (struct sfnt_edge *edges, size_t num_edges,
void *dcontext)
@@ -11182,14 +11454,13 @@ sfnt_test_edge (struct sfnt_edge *edges, size_t
num_edges,
for (i = 0; i < num_edges; ++i)
{
printf ("/* edge x, top, bot: %g, %g - %g. winding: %d */\n"
- "/* edge step_x: %g, source_x: %g (%d) */\n",
+ "/* edge step_x: %g, sign: %d */\n",
sfnt_coerce_fixed (edges[i].x),
sfnt_coerce_fixed (edges[i].top),
sfnt_coerce_fixed (edges[i].bottom),
edges[i].winding,
sfnt_coerce_fixed (edges[i].step_x),
- sfnt_coerce_fixed (edges[i].source_x),
- edges[i].source_x);
+ edges[i].signed_step);
#ifdef TEST_VERTEX
printf ("ctx.fillRect (%g, %g, 1, 1);\n",
sfnt_coerce_fixed (edges[i].x),
@@ -11203,11 +11474,133 @@ sfnt_test_edge (struct sfnt_edge *edges, size_t
num_edges,
#endif
}
+ if (getenv ("SFNT_DEBUG_STEP"))
+ {
+ if (!fork ())
+ sfnt_debug_edges (edges, num_edges);
+ }
+
printf ("==end of edges==\n");
sfnt_poly_edges (edges, num_edges, sfnt_test_span, NULL);
}
+static void
+sfnt_x_raster (struct sfnt_raster *raster)
+{
+ Display *display;
+ Window window;
+ Pixmap pixmap;
+ Picture glyph, drawable, solid;
+ int event_base, error_base;
+ int major, minor, *depths, count;
+ XRenderPictFormat *format, *glyph_format;
+ Visual *visual;
+ XImage image;
+ GC gc;
+ XGCValues gcvalues;
+ XEvent event;
+ XRenderColor white, black;
+ int i;
+
+ display = XOpenDisplay (NULL);
+
+ if (!display)
+ exit (0);
+
+ if (!XRenderQueryExtension (display, &event_base, &error_base)
+ || !XRenderQueryVersion (display, &major, &minor))
+ exit (0);
+
+ if (major == 0 && minor < 10)
+ exit (0);
+
+ window = XCreateSimpleWindow (display, DefaultRootWindow (display),
+ 0, 0, 40, 40, 0, 0,
+ WhitePixel (display,
+ DefaultScreen (display)));
+ XSelectInput (display, window, ExposureMask);
+ XMapWindow (display, window);
+
+ visual = DefaultVisual (display, DefaultScreen (display));
+ format = XRenderFindVisualFormat (display, visual);
+
+ if (!format)
+ exit (0);
+
+ glyph_format = XRenderFindStandardFormat (display, PictStandardA8);
+ depths = XListDepths (display, DefaultScreen (display), &count);
+
+ for (i = 0; i < count; ++i)
+ {
+ if (depths[i] == 8)
+ goto depth_found;
+ }
+
+ exit (0);
+
+ depth_found:
+
+ XFree (depths);
+ pixmap = XCreatePixmap (display, DefaultRootWindow (display),
+ raster->width, raster->height, 8);
+
+ /* Upload the raster. */
+ image.width = raster->width;
+ image.height = raster->height;
+ image.xoffset = 0;
+ image.format = ZPixmap;
+ image.data = (char *) raster->cells;
+ image.byte_order = MSBFirst;
+ image.bitmap_unit = 8;
+ image.bitmap_bit_order = LSBFirst;
+ image.bitmap_pad = SFNT_POLY_ALIGNMENT * 8;
+ image.depth = 8;
+ image.bytes_per_line = raster->stride;
+ image.bits_per_pixel = 8;
+ image.red_mask = 0;
+ image.green_mask = 0;
+ image.blue_mask = 0;
+
+ if (!XInitImage (&image))
+ abort ();
+
+ gc = XCreateGC (display, pixmap, 0, &gcvalues);
+ XPutImage (display, pixmap, gc, &image,
+ 0, 0, 0, 0, image.width, image.height);
+
+ drawable = XRenderCreatePicture (display, window, format,
+ 0, NULL);
+ glyph = XRenderCreatePicture (display, pixmap, glyph_format,
+ 0, NULL);
+ memset (&black, 0, sizeof black);
+ black.alpha = 65535;
+
+ solid = XRenderCreateSolidFill (display, &black);
+
+ while (true)
+ {
+ XNextEvent (display, &event);
+
+ if (event.type == Expose)
+ {
+ white.red = 65535;
+ white.green = 65535;
+ white.blue = 65535;
+ white.alpha = 65535;
+
+ /* Clear the background. */
+ XRenderFillRectangle (display, PictOpSrc, drawable,
+ &white, 0, 0, 65535, 65535);
+
+ /* Draw the solid fill with the glyph as clip mask. */
+ XRenderComposite (display, PictOpOver, solid, glyph,
+ drawable, 0, 0, 0, 0, 0, 0,
+ raster->width, raster->height);
+ }
+ }
+}
+
static void
sfnt_test_raster (struct sfnt_raster *raster)
{
@@ -11219,6 +11612,12 @@ sfnt_test_raster (struct sfnt_raster *raster)
printf ("%3d ", (int) raster->cells[y * raster->stride + x]);
puts ("");
}
+
+ if (getenv ("SFNT_X"))
+ {
+ if (!fork ())
+ sfnt_x_raster (raster);
+ }
}
@@ -12060,7 +12459,7 @@ static struct sfnt_generic_test_args wcvtp_test_args =
static struct sfnt_generic_test_args rcvt_test_args =
{
- (uint32_t []) { 135, },
+ (uint32_t []) { 136, },
1,
true,
5,
@@ -12309,8 +12708,8 @@ static struct sfnt_generic_test_args jrof_test_args =
static struct sfnt_generic_test_args deltac1_test_args =
{
- (uint32_t []) { ((50 * 17 * 65535 / 800) >> 10) + 8,
- ((50 * 17 * 65535 / 800) >> 10) + 8, },
+ (uint32_t []) { ((((50 * 17 * 65535) + 32767) / 800) >> 10) + 8,
+ ((((50 * 17 * 65535) + 32767) / 800) >> 10) + 8, },
2,
false,
22,
@@ -12318,8 +12717,8 @@ static struct sfnt_generic_test_args deltac1_test_args =
static struct sfnt_generic_test_args deltac2_test_args =
{
- (uint32_t []) { ((50 * 17 * 65535 / 800) >> 10) + 8,
- ((50 * 17 * 65535 / 800) >> 10) + 8, },
+ (uint32_t []) { ((((50 * 17 * 65535) + 32767) / 800) >> 10) + 8,
+ ((((50 * 17 * 65535) + 32767) / 800) >> 10) + 8, },
2,
false,
22,
@@ -12327,8 +12726,8 @@ static struct sfnt_generic_test_args deltac2_test_args =
static struct sfnt_generic_test_args deltac3_test_args =
{
- (uint32_t []) { ((50 * 17 * 65535 / 800) >> 10) + 8,
- ((50 * 17 * 65535 / 800) >> 10) + 8, },
+ (uint32_t []) { ((((50 * 17 * 65535) + 32767) / 800) >> 10) + 8,
+ ((((50 * 17 * 65535) + 32767) / 800) >> 10) + 8, },
2,
false,
22,
@@ -12489,8 +12888,8 @@ static struct sfnt_generic_test_args roll_test_args =
static struct sfnt_generic_test_args roll_1_test_args =
{
- (uint32_t []) { },
- 0,
+ (uint32_t []) { 1, 2, },
+ 2,
true,
3,
};
@@ -13993,15 +14392,6 @@ static struct sfnt_interpreter_test all_tests[] =
/* Instruction debugger. */
-/* The debugger's X display. */
-static Display *display;
-
-/* The debugger window. */
-static Window window;
-
-/* The GC. */
-static GC point_gc, background_gc;
-
static void
sfnt_setup_debugger (void)
{
@@ -14383,6 +14773,13 @@ sfnt_run_hook (struct sfnt_interpreter *interpreter)
pid_t pid;
XEvent event;
+#ifdef TEST_BREAK_AFTER
+ static unsigned int instructions;
+
+ if (++instructions < TEST_BREAK_AFTER)
+ return;
+#endif
+
pid = fork ();
if (pid == 0)
@@ -14414,6 +14811,41 @@ sfnt_run_hook (struct sfnt_interpreter *interpreter)
}
}
+static struct sfnt_prep_table *exec_prep;
+static struct sfnt_fpgm_table *exec_fpgm;
+
+static const char *
+sfnt_identify_instruction (struct sfnt_interpreter *interpreter)
+{
+ static char buffer[256];
+ unsigned char *where;
+
+ where = interpreter->instructions + interpreter->IP;
+
+ if (exec_prep
+ && where >= exec_prep->instructions
+ && where < (exec_prep->instructions
+ + exec_prep->num_instructions))
+ {
+ sprintf (buffer, "prep+%td",
+ where - exec_prep->instructions);
+ return buffer;
+ }
+
+ if (exec_fpgm->instructions
+ && where >= exec_fpgm->instructions
+ && where < (exec_fpgm->instructions
+ + exec_fpgm->num_instructions))
+ {
+ sprintf (buffer, "fpgm+%td",
+ where - exec_fpgm->instructions);
+ return buffer;
+ }
+
+ sprintf (buffer, "IP+%td", where - interpreter->instructions);
+ return buffer;
+}
+
static void
sfnt_verbose (struct sfnt_interpreter *interpreter)
{
@@ -14421,6 +14853,8 @@ sfnt_verbose (struct sfnt_interpreter *interpreter)
struct sfnt_glyph_outline *outline;
struct sfnt_raster *raster;
unsigned char opcode;
+ const char *name;
+ static unsigned int instructions;
/* Build a temporary outline containing the values of the
interpreter's glyph zone. */
@@ -14444,7 +14878,43 @@ sfnt_verbose (struct sfnt_interpreter *interpreter)
xfree (raster);
opcode = interpreter->instructions[interpreter->IP];
- printf ("opcode: %s\n", sfnt_name_instruction (opcode));
+ printf ("opcode, number of instructions: %s %u\n",
+ sfnt_name_instruction (opcode), instructions++);
+ printf ("instruction: %s\n",
+ sfnt_identify_instruction (interpreter));
+
+ if (interpreter->state.project
+ == sfnt_project_onto_x_axis_vector)
+ name = "X axis";
+ else if (interpreter->state.project
+ == sfnt_project_onto_y_axis_vector)
+ name = "Y axis";
+ else
+ name = "Any";
+
+ printf ("projection function: %s\n", name);
+}
+
+static void
+sfnt_push_hook (struct sfnt_interpreter *interpreter,
+ uint32_t value)
+{
+ int32_t alternate;
+
+ alternate = value;
+
+ fprintf (stderr, "--> %"PRIi32"\n", alternate);
+}
+
+static void
+sfnt_pop_hook (struct sfnt_interpreter *interpreter,
+ uint32_t value)
+{
+ int32_t alternate;
+
+ alternate = value;
+
+ fprintf (stderr, "<<- %"PRIi32"\n", alternate);
}
@@ -14473,7 +14943,7 @@ sfnt_verbose (struct sfnt_interpreter *interpreter)
-Wno-missing-field-initializers -Wno-override-init
-Wno-sign-compare -Wno-type-limits -Wno-unused-parameter
-Wno-format-nonliteral -Wno-bidi-chars -g3 -O0 -DTEST sfnt.c -o
- sfnt ../lib/libgnu.a -lX11
+ sfnt ../lib/libgnu.a -lX11 -lXrender
after gnulib has been built. Then, run ./sfnt
/path/to/font.ttf. */
@@ -14496,7 +14966,7 @@ main (int argc, char **argv)
sfnt_glyph code;
struct sfnt_test_dcontext dcontext;
struct sfnt_glyph_outline *outline;
- struct timespec start, end, sub, sub1, sub2;
+ struct timespec start, end, sub, sub1, sub2, sub3;
static struct sfnt_maxp_table *maxp;
struct sfnt_raster *raster;
struct sfnt_hmtx_table *hmtx;
@@ -14613,6 +15083,9 @@ main (int argc, char **argv)
prep = sfnt_read_prep_table (fd, font);
hmtx = NULL;
+ exec_prep = prep;
+ exec_fpgm = fpgm;
+
if (head && maxp && maxp->version >= 0x00010000)
{
fprintf (stderr, "creating interpreter\n"
@@ -14696,7 +15169,7 @@ main (int argc, char **argv)
"checksum_adjustment: \t\t%"PRIu32"\n"
"magic: \t\t\t\t%"PRIx32"\n"
"flags: \t\t\t\t%"PRIx16"\n"
- "units_per_em: \t\t\t%"PRIx16"\n"
+ "units_per_em: \t\t\t%"PRIu16"\n"
"xmin, ymin, xmax, ymax: \t%d, %d, %d, %d\n"
"mac_style: \t\t\t%"PRIx16"\n"
"lowest_rec_ppem: \t\t%"PRIu16"\n"
@@ -14848,7 +15321,7 @@ main (int argc, char **argv)
clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start);
- for (i = 0; i < 400; ++i)
+ for (i = 0; i < 1; ++i)
{
xfree (raster);
raster = sfnt_raster_glyph_outline (outline);
@@ -14886,7 +15359,11 @@ main (int argc, char **argv)
if (getenv ("SFNT_DEBUG"))
interpreter->run_hook = sfnt_run_hook;
else if (getenv ("SFNT_VERBOSE"))
- interpreter->run_hook = sfnt_verbose;
+ {
+ interpreter->run_hook = sfnt_verbose;
+ interpreter->push_hook = sfnt_push_hook;
+ interpreter->pop_hook = sfnt_pop_hook;
+ }
if (glyph->simple
&& sfnt_lookup_glyph_metrics (code, -1,
@@ -14896,8 +15373,11 @@ main (int argc, char **argv)
{
printf ("interpreting glyph\n");
interpreter->state = state;
+ clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start);
trap = sfnt_interpret_simple_glyph (glyph,
interpreter,
&metrics, &value);
+ clock_gettime (CLOCK_THREAD_CPUTIME_ID, &end);
+ sub3 = timespec_sub (end, start);
if (trap)
printf ("**TRAP**: %s\n", trap);
@@ -14920,6 +15400,9 @@ main (int argc, char **argv)
}
}
}
+
+ fprintf (stderr, "execution time: %lld sec %ld
nsec\n",
+ (long long) sub3.tv_sec, sub3.tv_nsec);
}
interpreter->run_hook = NULL;
@@ -14931,7 +15414,7 @@ main (int argc, char **argv)
printf ("time spent building edges: %lld sec %ld nsec\n",
(long long) sub1.tv_sec, sub1.tv_nsec);
printf ("time spent rasterizing: %lld sec %ld nsec\n",
- (long long) sub2.tv_sec / 400, sub2.tv_nsec / 400);
+ (long long) sub2.tv_sec / 1, sub2.tv_nsec / 1);
xfree (outline);
}
diff --git a/src/sfnt.h b/src/sfnt.h
index baed1d257d..4852296004 100644
--- a/src/sfnt.h
+++ b/src/sfnt.h
@@ -698,6 +698,13 @@ struct sfnt_raster
unsigned short refcount;
};
+/* Bresenham's algorithm.
+ This rasterizer uses Bresenham's algorithm, with the minor
+ detail being that it does not use device pixels, but rather
+ pixels in a sample grid defined by SFNT_POLY_SHIFT, which is
+ normally set to 4x oversampling. See sfnt_poly_edges for
+ an explanation of how Bresenham's algorithm works. */
+
struct sfnt_edge
{
/* Next edge in this chain. */
@@ -709,15 +716,14 @@ struct sfnt_edge
/* X position, top and bottom of edges. */
sfnt_fixed x, top, bottom;
- /* step_x is how many pixels to move for each increase in Y by
- SFNT_POLY_STEP. */
+ /* Slope error. */
sfnt_fixed step_x;
-#ifdef TEST
- /* Value of x before initial adjustment of bottom to match the
- grid. */
- sfnt_fixed source_x;
-#endif
+ /* SFNT_POLY_STEP times the direction of movement. */
+ sfnt_fixed signed_step;
+
+ /* Slope error accumulator. */
+ sfnt_fixed error;
};
@@ -731,7 +737,6 @@ enum
SFNT_POLY_MASK = (SFNT_POLY_SAMPLE - 1),
SFNT_POLY_STEP = (0x10000 >> SFNT_POLY_SHIFT),
SFNT_POLY_START = (SFNT_POLY_STEP >> 1),
- SFNT_POLY_ROUND = ((1 << (16 - SFNT_POLY_SHIFT)) / 2) - 1,
};