From: kiirala Date: Mon, 23 Jul 2007 08:12:06 +0000 (+0000) Subject: Patch by Jean-René Reinhard: better SVG compliance for lighting effects X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=0f1b8f53ed81c3a02f55223cd3eb359f123bc565;p=inkscape.git Patch by Jean-René Reinhard: better SVG compliance for lighting effects --- diff --git a/src/display/Makefile_insert b/src/display/Makefile_insert index eaa2f584f..a72175b3f 100644 --- a/src/display/Makefile_insert +++ b/src/display/Makefile_insert @@ -89,6 +89,8 @@ display_libspdisplay_a_SOURCES = \ display/nr-filter-getalpha.h \ display/nr-filter-pixops.h \ display/nr-filter-types.h \ + display/nr-filter-utils.h \ + display/nr-filter-utils.cpp \ display/pixblock-scaler.cpp \ display/pixblock-scaler.h \ display/pixblock-transform.cpp \ diff --git a/src/display/nr-filter-composite.cpp b/src/display/nr-filter-composite.cpp index 43580191e..a5b1d5297 100644 --- a/src/display/nr-filter-composite.cpp +++ b/src/display/nr-filter-composite.cpp @@ -16,6 +16,7 @@ #include "display/nr-filter-composite.h" #include "display/nr-filter-pixops.h" #include "display/nr-filter-slot.h" +#include "display/nr-filter-utils.h" #include "libnr/nr-blit.h" #include "libnr/nr-pixblock.h" #include "libnr/nr-pixops.h" @@ -66,25 +67,19 @@ composite_xor(unsigned char *r, unsigned char const *a, unsigned char const *b) r[3] = NR_NORMALIZE_21(a[3] * (255 - b[3]) + b[3] * (255 - a[3])); } -static int clamp(int val) { - if (val < 0) return 0; - if (val > 255) return 255; - return val; -} - // BUGBUG / TODO // This makes arithmetic compositing non re-entrant and non thread safe. static int arith_k1, arith_k2, arith_k3, arith_k4; inline void composite_arithmetic(unsigned char *r, unsigned char const *a, unsigned char const *b) { - r[0] = clamp(NR_NORMALIZE_31(arith_k1 * a[0] * b[0] + r[0] = NR::clamp(NR_NORMALIZE_31(arith_k1 * a[0] * b[0] + arith_k2 * a[0] + arith_k3 * b[0] + arith_k4)); - r[1] = clamp(NR_NORMALIZE_31(arith_k1 * a[1] * b[1] + r[1] = NR::clamp(NR_NORMALIZE_31(arith_k1 * a[1] * b[1] + arith_k2 * a[1] + arith_k3 * b[1] + arith_k4)); - r[2] = clamp(NR_NORMALIZE_31(arith_k1 * a[2] * b[2] + r[2] = NR::clamp(NR_NORMALIZE_31(arith_k1 * a[2] * b[2] + arith_k2 * a[2] + arith_k3 * b[2] + arith_k4)); - r[3] = clamp(NR_NORMALIZE_31(arith_k1 * a[3] * b[3] + r[3] = NR::clamp(NR_NORMALIZE_31(arith_k1 * a[3] * b[3] + arith_k2 * a[3] + arith_k3 * b[3] + arith_k4)); } diff --git a/src/display/nr-filter-diffuselighting.cpp b/src/display/nr-filter-diffuselighting.cpp index 736055f32..96a2e9ca6 100644 --- a/src/display/nr-filter-diffuselighting.cpp +++ b/src/display/nr-filter-diffuselighting.cpp @@ -17,13 +17,13 @@ #include "display/nr-filter-diffuselighting.h" #include "display/nr-filter-getalpha.h" #include "display/nr-filter-slot.h" +#include "display/nr-filter-utils.h" #include "display/nr-light.h" #include "libnr/nr-blit.h" #include "libnr/nr-pixblock.h" #include "libnr/nr-matrix.h" #include "libnr/nr-rect-l.h" #include "color.h" -#include "round.h" namespace NR { @@ -48,6 +48,7 @@ do {\ if ((inter) < 0) (inter) = 0; \ }while(0) + int FilterDiffuseLighting::render(FilterSlot &slot, Matrix const &trans) { NRPixBlock *in = filter_get_alpha(slot.get(_input)); NRPixBlock *out = new NRPixBlock; @@ -87,9 +88,9 @@ int FilterDiffuseLighting::render(FilterSlot &slot, Matrix const &trans) { compute_surface_normal(N, ss, in, i / w, i % w, dx, dy); COMPUTE_INTER(inter, N, L, kd); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]); data_o[j++] = 255; } out->empty = FALSE; @@ -113,9 +114,9 @@ int FilterDiffuseLighting::render(FilterSlot &slot, Matrix const &trans) { ss * (double) data_i[4*i+3]/ 255); COMPUTE_INTER(inter, N, L, kd); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]); data_o[j++] = 255; } out->empty = FALSE; @@ -139,9 +140,9 @@ int FilterDiffuseLighting::render(FilterSlot &slot, Matrix const &trans) { sl->light_components(LC, L); COMPUTE_INTER(inter, N, L, kd); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]); data_o[j++] = 255; } out->empty = FALSE; diff --git a/src/display/nr-filter-specularlighting.cpp b/src/display/nr-filter-specularlighting.cpp index 117df28f7..9957f4d59 100644 --- a/src/display/nr-filter-specularlighting.cpp +++ b/src/display/nr-filter-specularlighting.cpp @@ -18,13 +18,13 @@ #include "display/nr-filter-specularlighting.h" #include "display/nr-filter-getalpha.h" #include "display/nr-filter-slot.h" +#include "display/nr-filter-utils.h" #include "display/nr-light.h" #include "libnr/nr-blit.h" #include "libnr/nr-pixblock.h" #include "libnr/nr-matrix.h" #include "libnr/nr-rect-l.h" #include "color.h" -#include "round.h" namespace NR { @@ -46,10 +46,12 @@ FilterSpecularLighting::~FilterSpecularLighting() //Investigating Phong Lighting model we should not take N.H but //R.E which equals to 2*N.H^2 - 1 +//replace the second line by +//gdouble scal = scalar_product((N), (H)); scal = 2 * scal * scal - 1;\ +//to get the expected formula #define COMPUTE_INTER(inter, H, N, ks, speculaExponent) \ do {\ - gdouble scal = scalar_product((N), (H));\ - scal = 2 * scal * scal - 1;\ + gdouble scal = scalar_product((N), (H)); \ if (scal <= 0)\ (inter) = 0;\ else\ @@ -97,9 +99,9 @@ int FilterSpecularLighting::render(FilterSlot &slot, Matrix const &trans) { compute_surface_normal(N, ss, in, i / w, i % w, dx, dy); COMPUTE_INTER(inter, N, H, ks, specularExponent); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]); data_o[j++] = MAX(MAX(data_o[j-3], data_o[j-2]), data_o[j-1]); } out->empty = FALSE; @@ -124,9 +126,9 @@ int FilterSpecularLighting::render(FilterSlot &slot, Matrix const &trans) { normalized_sum(H, L, EYE_VECTOR); COMPUTE_INTER(inter, N, H, ks, specularExponent); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]); data_o[j++] = MAX(MAX(data_o[j-3], data_o[j-2]), data_o[j-1]); } out->empty = FALSE; @@ -151,9 +153,9 @@ int FilterSpecularLighting::render(FilterSlot &slot, Matrix const &trans) { normalized_sum(H, L, EYE_VECTOR); COMPUTE_INTER(inter, N, H, ks, specularExponent); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_RED]); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_GREEN]); - data_o[j++] = (unsigned char) round(inter * LC[LIGHT_BLUE]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]); + data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]); data_o[j++] = MAX(MAX(data_o[j-3], data_o[j-2]), data_o[j-1]); } out->empty = FALSE; diff --git a/src/display/nr-filter-utils.cpp b/src/display/nr-filter-utils.cpp new file mode 100644 index 000000000..85faadebc --- /dev/null +++ b/src/display/nr-filter-utils.cpp @@ -0,0 +1,11 @@ +#include "nr-filter-utils.h" + +namespace NR { + +int clamp(int val) { + if (val < 0) return 0; + if (val > 255) return 255; + return val; +} + +} //namespace NR diff --git a/src/display/nr-filter-utils.h b/src/display/nr-filter-utils.h new file mode 100644 index 000000000..b591b37cb --- /dev/null +++ b/src/display/nr-filter-utils.h @@ -0,0 +1,45 @@ +#ifndef __NR_FILTER_UTILS_H__ +#define __NR_FILTER_UTILS_H__ + +/** \file + * filter utils. Definition of functions needed by several filters. + * + * Authors: + * Jean-Rene Reinhard + * + * Copyright (C) 2007 authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "round.h" + +namespace NR { + +/** + * Clamps an integer value to a value between 0 and 255. Needed by filters where + * rendering computations can lead to component values out of bound. + * + * \return 0 if the value is smaller than 0, 255 if it is greater 255, else v + * \param v the value to clamp + */ +int clamp(int val); + +/** + * Macro to use the clamp function with double inputs and unsigned char output + */ +#define CLAMP_D_TO_U8(v) (unsigned char) clamp((int)round((v))) + +} /* namespace NR */ + +#endif /* __NR_FILTER_UTILS_H__ */ +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :