add oversampler
This commit is contained in:
115
oversampling/WDL/lice/curverasterbuffer.h
Normal file
115
oversampling/WDL/lice/curverasterbuffer.h
Normal file
@@ -0,0 +1,115 @@
|
||||
#ifndef _LICE_CURVE_RASTER_BUFFER_H_
|
||||
#define _LICE_CURVE_RASTER_BUFFER_H_
|
||||
|
||||
class CurveRasterBuffer
|
||||
{
|
||||
static void CopyPixelNoClip(LICE_IBitmap *bmp, int x, int y, LICE_pixel col, double alpha)
|
||||
{
|
||||
LICE_pixel *p=bmp->getBits()+y*bmp->getRowSpan()+x;
|
||||
if (*p == col || alpha <= 0.0) return;
|
||||
|
||||
if (alpha >= 1.0)
|
||||
{
|
||||
*p=col;
|
||||
return;
|
||||
}
|
||||
|
||||
const int ia=256-(int)(alpha*256.0);
|
||||
int r=LICE_GETR(col), g=LICE_GETG(col), b=LICE_GETB(col);
|
||||
LICE_pixel_chan *c=(LICE_pixel_chan*)p;
|
||||
c[LICE_PIXEL_R]=r+((c[LICE_PIXEL_R]-r)*ia)/256;
|
||||
c[LICE_PIXEL_G]=g+((c[LICE_PIXEL_G]-g)*ia)/256;
|
||||
c[LICE_PIXEL_B]=b+((c[LICE_PIXEL_B]-b)*ia)/256;
|
||||
}
|
||||
|
||||
static void DrawSlice(LICE_IBitmap* bmp, int x, double y1, double y2, int pxh, LICE_pixel color, float alpha)
|
||||
{
|
||||
const int iy1=(int)y1, iy2=(int)y2;
|
||||
|
||||
if (iy1 == iy2)
|
||||
{
|
||||
if (iy1 >= 0 && iy1 < pxh) CopyPixelNoClip(bmp, x, iy1, color, (y2-y1)*alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (iy1 >= 0 && iy1 < pxh) CopyPixelNoClip(bmp, x, iy1, color, (1+iy1-y1)*alpha);
|
||||
|
||||
if (iy2 > iy1+1)
|
||||
{
|
||||
int iy;
|
||||
const int n=min(iy2, pxh);
|
||||
for (iy=max(iy1+1, 0); iy < n; ++iy)
|
||||
{
|
||||
CopyPixelNoClip(bmp, x, iy, color, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
if (iy2 >= 0 && iy2 < pxh) CopyPixelNoClip(bmp, x, iy2, color, (y2-iy2)*alpha);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
int xext[2],bmw;
|
||||
float *sb;
|
||||
|
||||
CurveRasterBuffer(int w, WDL_TypedBuf<float> *sbuf)
|
||||
{
|
||||
xext[0]=bmw=w;
|
||||
xext[1]=0;
|
||||
sb = sbuf->ResizeOK(w*2,false);
|
||||
}
|
||||
|
||||
void addpt(int xpos, double ypos)
|
||||
{
|
||||
if (xpos >= 0 && xpos < bmw)
|
||||
{
|
||||
float *p = sb + xpos*2;
|
||||
const int ext0=xext[0], ext1=xext[1];
|
||||
if (ext0 <= ext1) // existing range
|
||||
{
|
||||
if (xpos < ext0)
|
||||
{
|
||||
memset(p+2, 0, (ext0-xpos-1)*2*sizeof(*p));
|
||||
p[0]=p[1]=ypos;
|
||||
xext[0]=xpos;
|
||||
}
|
||||
else if (xpos > ext1)
|
||||
{
|
||||
memset(sb + (ext1+1)*2, 0, (xpos-(ext1+1))*2*sizeof(*p));
|
||||
p[0]=p[1]=ypos;
|
||||
xext[1]=xpos;
|
||||
}
|
||||
else if (p[0] == 0.0 && p[1] == 0.0) p[0] = p[1] = ypos;
|
||||
else
|
||||
{
|
||||
if (ypos < p[0]) p[0] = ypos;
|
||||
else if (ypos > p[1]) p[1] = ypos;
|
||||
}
|
||||
}
|
||||
else // first point
|
||||
{
|
||||
xext[0]=xext[1] = xpos;
|
||||
p[0]=p[1]=ypos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Draw(LICE_IBitmap *bm, LICE_pixel color, float alpha)
|
||||
{
|
||||
int bmh = bm->getHeight();
|
||||
const int sc = (int) (INT_PTR)bm->Extended(LICE_EXT_GET_SCALING,NULL);
|
||||
if (sc > 256) bmh = bmh * sc / 256;
|
||||
const int xmax = xext[1];
|
||||
int x = xext[0];
|
||||
const float *sbuf = sb+x*2;
|
||||
for (; x <= xmax; x ++)
|
||||
{
|
||||
const double v1 = sbuf[0], v2 = sbuf[1];
|
||||
if (v2>v1) DrawSlice(bm, x,v1,v2, bmh, color,alpha);
|
||||
sbuf+= 2;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
631
oversampling/WDL/lice/glew/include/GL/WGLEXT.H
Normal file
631
oversampling/WDL/lice/glew/include/GL/WGLEXT.H
Normal file
@@ -0,0 +1,631 @@
|
||||
#ifndef __wglext_h_
|
||||
#define __wglext_h_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
** License Applicability. Except to the extent portions of this file are
|
||||
** made subject to an alternative license as permitted in the SGI Free
|
||||
** Software License B, Version 1.1 (the "License"), the contents of this
|
||||
** file are subject only to the provisions of the License. You may not use
|
||||
** this file except in compliance with the License. You may obtain a copy
|
||||
** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
|
||||
** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
|
||||
**
|
||||
** http://oss.sgi.com/projects/FreeB
|
||||
**
|
||||
** Note that, as provided in the License, the Software is distributed on an
|
||||
** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
|
||||
** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
|
||||
** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
|
||||
** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
||||
**
|
||||
** Original Code. The Original Code is: OpenGL Sample Implementation,
|
||||
** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
|
||||
** Inc. The Original Code is Copyright (c) 1991-2004 Silicon Graphics, Inc.
|
||||
** Copyright in any portions created by third parties is as indicated
|
||||
** elsewhere herein. All Rights Reserved.
|
||||
**
|
||||
** Additional Notice Provisions: This software was created using the
|
||||
** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has
|
||||
** not been independently verified as being compliant with the OpenGL(R)
|
||||
** version 1.2.1 Specification.
|
||||
*/
|
||||
|
||||
#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifndef APIENTRY
|
||||
#define APIENTRY
|
||||
#endif
|
||||
#ifndef APIENTRYP
|
||||
#define APIENTRYP APIENTRY *
|
||||
#endif
|
||||
#ifndef GLAPI
|
||||
#define GLAPI extern
|
||||
#endif
|
||||
|
||||
/*************************************************************/
|
||||
|
||||
/* Header file version number */
|
||||
/* wglext.h last updated 2005/01/07 */
|
||||
/* Current version at http://oss.sgi.com/projects/ogl-sample/registry/ */
|
||||
#define WGL_WGLEXT_VERSION 6
|
||||
|
||||
#ifndef WGL_ARB_buffer_region
|
||||
#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001
|
||||
#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002
|
||||
#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004
|
||||
#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ARB_multisample
|
||||
#define WGL_SAMPLE_BUFFERS_ARB 0x2041
|
||||
#define WGL_SAMPLES_ARB 0x2042
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ARB_extensions_string
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ARB_pixel_format
|
||||
#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
|
||||
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
|
||||
#define WGL_DRAW_TO_BITMAP_ARB 0x2002
|
||||
#define WGL_ACCELERATION_ARB 0x2003
|
||||
#define WGL_NEED_PALETTE_ARB 0x2004
|
||||
#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
|
||||
#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
|
||||
#define WGL_SWAP_METHOD_ARB 0x2007
|
||||
#define WGL_NUMBER_OVERLAYS_ARB 0x2008
|
||||
#define WGL_NUMBER_UNDERLAYS_ARB 0x2009
|
||||
#define WGL_TRANSPARENT_ARB 0x200A
|
||||
#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
|
||||
#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
|
||||
#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
|
||||
#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
|
||||
#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
|
||||
#define WGL_SHARE_DEPTH_ARB 0x200C
|
||||
#define WGL_SHARE_STENCIL_ARB 0x200D
|
||||
#define WGL_SHARE_ACCUM_ARB 0x200E
|
||||
#define WGL_SUPPORT_GDI_ARB 0x200F
|
||||
#define WGL_SUPPORT_OPENGL_ARB 0x2010
|
||||
#define WGL_DOUBLE_BUFFER_ARB 0x2011
|
||||
#define WGL_STEREO_ARB 0x2012
|
||||
#define WGL_PIXEL_TYPE_ARB 0x2013
|
||||
#define WGL_COLOR_BITS_ARB 0x2014
|
||||
#define WGL_RED_BITS_ARB 0x2015
|
||||
#define WGL_RED_SHIFT_ARB 0x2016
|
||||
#define WGL_GREEN_BITS_ARB 0x2017
|
||||
#define WGL_GREEN_SHIFT_ARB 0x2018
|
||||
#define WGL_BLUE_BITS_ARB 0x2019
|
||||
#define WGL_BLUE_SHIFT_ARB 0x201A
|
||||
#define WGL_ALPHA_BITS_ARB 0x201B
|
||||
#define WGL_ALPHA_SHIFT_ARB 0x201C
|
||||
#define WGL_ACCUM_BITS_ARB 0x201D
|
||||
#define WGL_ACCUM_RED_BITS_ARB 0x201E
|
||||
#define WGL_ACCUM_GREEN_BITS_ARB 0x201F
|
||||
#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
|
||||
#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
|
||||
#define WGL_DEPTH_BITS_ARB 0x2022
|
||||
#define WGL_STENCIL_BITS_ARB 0x2023
|
||||
#define WGL_AUX_BUFFERS_ARB 0x2024
|
||||
#define WGL_NO_ACCELERATION_ARB 0x2025
|
||||
#define WGL_GENERIC_ACCELERATION_ARB 0x2026
|
||||
#define WGL_FULL_ACCELERATION_ARB 0x2027
|
||||
#define WGL_SWAP_EXCHANGE_ARB 0x2028
|
||||
#define WGL_SWAP_COPY_ARB 0x2029
|
||||
#define WGL_SWAP_UNDEFINED_ARB 0x202A
|
||||
#define WGL_TYPE_RGBA_ARB 0x202B
|
||||
#define WGL_TYPE_COLORINDEX_ARB 0x202C
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ARB_make_current_read
|
||||
#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043
|
||||
#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ARB_pbuffer
|
||||
#define WGL_DRAW_TO_PBUFFER_ARB 0x202D
|
||||
#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E
|
||||
#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F
|
||||
#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030
|
||||
#define WGL_PBUFFER_LARGEST_ARB 0x2033
|
||||
#define WGL_PBUFFER_WIDTH_ARB 0x2034
|
||||
#define WGL_PBUFFER_HEIGHT_ARB 0x2035
|
||||
#define WGL_PBUFFER_LOST_ARB 0x2036
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ARB_render_texture
|
||||
#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070
|
||||
#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071
|
||||
#define WGL_TEXTURE_FORMAT_ARB 0x2072
|
||||
#define WGL_TEXTURE_TARGET_ARB 0x2073
|
||||
#define WGL_MIPMAP_TEXTURE_ARB 0x2074
|
||||
#define WGL_TEXTURE_RGB_ARB 0x2075
|
||||
#define WGL_TEXTURE_RGBA_ARB 0x2076
|
||||
#define WGL_NO_TEXTURE_ARB 0x2077
|
||||
#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078
|
||||
#define WGL_TEXTURE_1D_ARB 0x2079
|
||||
#define WGL_TEXTURE_2D_ARB 0x207A
|
||||
#define WGL_MIPMAP_LEVEL_ARB 0x207B
|
||||
#define WGL_CUBE_MAP_FACE_ARB 0x207C
|
||||
#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D
|
||||
#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E
|
||||
#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F
|
||||
#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080
|
||||
#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081
|
||||
#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082
|
||||
#define WGL_FRONT_LEFT_ARB 0x2083
|
||||
#define WGL_FRONT_RIGHT_ARB 0x2084
|
||||
#define WGL_BACK_LEFT_ARB 0x2085
|
||||
#define WGL_BACK_RIGHT_ARB 0x2086
|
||||
#define WGL_AUX0_ARB 0x2087
|
||||
#define WGL_AUX1_ARB 0x2088
|
||||
#define WGL_AUX2_ARB 0x2089
|
||||
#define WGL_AUX3_ARB 0x208A
|
||||
#define WGL_AUX4_ARB 0x208B
|
||||
#define WGL_AUX5_ARB 0x208C
|
||||
#define WGL_AUX6_ARB 0x208D
|
||||
#define WGL_AUX7_ARB 0x208E
|
||||
#define WGL_AUX8_ARB 0x208F
|
||||
#define WGL_AUX9_ARB 0x2090
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ARB_pixel_format_float
|
||||
#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0
|
||||
#endif
|
||||
|
||||
#ifndef WGL_EXT_make_current_read
|
||||
#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043
|
||||
#endif
|
||||
|
||||
#ifndef WGL_EXT_pixel_format
|
||||
#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000
|
||||
#define WGL_DRAW_TO_WINDOW_EXT 0x2001
|
||||
#define WGL_DRAW_TO_BITMAP_EXT 0x2002
|
||||
#define WGL_ACCELERATION_EXT 0x2003
|
||||
#define WGL_NEED_PALETTE_EXT 0x2004
|
||||
#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005
|
||||
#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006
|
||||
#define WGL_SWAP_METHOD_EXT 0x2007
|
||||
#define WGL_NUMBER_OVERLAYS_EXT 0x2008
|
||||
#define WGL_NUMBER_UNDERLAYS_EXT 0x2009
|
||||
#define WGL_TRANSPARENT_EXT 0x200A
|
||||
#define WGL_TRANSPARENT_VALUE_EXT 0x200B
|
||||
#define WGL_SHARE_DEPTH_EXT 0x200C
|
||||
#define WGL_SHARE_STENCIL_EXT 0x200D
|
||||
#define WGL_SHARE_ACCUM_EXT 0x200E
|
||||
#define WGL_SUPPORT_GDI_EXT 0x200F
|
||||
#define WGL_SUPPORT_OPENGL_EXT 0x2010
|
||||
#define WGL_DOUBLE_BUFFER_EXT 0x2011
|
||||
#define WGL_STEREO_EXT 0x2012
|
||||
#define WGL_PIXEL_TYPE_EXT 0x2013
|
||||
#define WGL_COLOR_BITS_EXT 0x2014
|
||||
#define WGL_RED_BITS_EXT 0x2015
|
||||
#define WGL_RED_SHIFT_EXT 0x2016
|
||||
#define WGL_GREEN_BITS_EXT 0x2017
|
||||
#define WGL_GREEN_SHIFT_EXT 0x2018
|
||||
#define WGL_BLUE_BITS_EXT 0x2019
|
||||
#define WGL_BLUE_SHIFT_EXT 0x201A
|
||||
#define WGL_ALPHA_BITS_EXT 0x201B
|
||||
#define WGL_ALPHA_SHIFT_EXT 0x201C
|
||||
#define WGL_ACCUM_BITS_EXT 0x201D
|
||||
#define WGL_ACCUM_RED_BITS_EXT 0x201E
|
||||
#define WGL_ACCUM_GREEN_BITS_EXT 0x201F
|
||||
#define WGL_ACCUM_BLUE_BITS_EXT 0x2020
|
||||
#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021
|
||||
#define WGL_DEPTH_BITS_EXT 0x2022
|
||||
#define WGL_STENCIL_BITS_EXT 0x2023
|
||||
#define WGL_AUX_BUFFERS_EXT 0x2024
|
||||
#define WGL_NO_ACCELERATION_EXT 0x2025
|
||||
#define WGL_GENERIC_ACCELERATION_EXT 0x2026
|
||||
#define WGL_FULL_ACCELERATION_EXT 0x2027
|
||||
#define WGL_SWAP_EXCHANGE_EXT 0x2028
|
||||
#define WGL_SWAP_COPY_EXT 0x2029
|
||||
#define WGL_SWAP_UNDEFINED_EXT 0x202A
|
||||
#define WGL_TYPE_RGBA_EXT 0x202B
|
||||
#define WGL_TYPE_COLORINDEX_EXT 0x202C
|
||||
#endif
|
||||
|
||||
#ifndef WGL_EXT_pbuffer
|
||||
#define WGL_DRAW_TO_PBUFFER_EXT 0x202D
|
||||
#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E
|
||||
#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F
|
||||
#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030
|
||||
#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031
|
||||
#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032
|
||||
#define WGL_PBUFFER_LARGEST_EXT 0x2033
|
||||
#define WGL_PBUFFER_WIDTH_EXT 0x2034
|
||||
#define WGL_PBUFFER_HEIGHT_EXT 0x2035
|
||||
#endif
|
||||
|
||||
#ifndef WGL_EXT_depth_float
|
||||
#define WGL_DEPTH_FLOAT_EXT 0x2040
|
||||
#endif
|
||||
|
||||
#ifndef WGL_3DFX_multisample
|
||||
#define WGL_SAMPLE_BUFFERS_3DFX 0x2060
|
||||
#define WGL_SAMPLES_3DFX 0x2061
|
||||
#endif
|
||||
|
||||
#ifndef WGL_EXT_multisample
|
||||
#define WGL_SAMPLE_BUFFERS_EXT 0x2041
|
||||
#define WGL_SAMPLES_EXT 0x2042
|
||||
#endif
|
||||
|
||||
#ifndef WGL_I3D_digital_video_control
|
||||
#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050
|
||||
#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051
|
||||
#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052
|
||||
#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053
|
||||
#endif
|
||||
|
||||
#ifndef WGL_I3D_gamma
|
||||
#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E
|
||||
#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F
|
||||
#endif
|
||||
|
||||
#ifndef WGL_I3D_genlock
|
||||
#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044
|
||||
#define WGL_GENLOCK_SOURCE_EXTENAL_SYNC_I3D 0x2045
|
||||
#define WGL_GENLOCK_SOURCE_EXTENAL_FIELD_I3D 0x2046
|
||||
#define WGL_GENLOCK_SOURCE_EXTENAL_TTL_I3D 0x2047
|
||||
#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048
|
||||
#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049
|
||||
#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A
|
||||
#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B
|
||||
#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C
|
||||
#endif
|
||||
|
||||
#ifndef WGL_I3D_image_buffer
|
||||
#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001
|
||||
#define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002
|
||||
#endif
|
||||
|
||||
#ifndef WGL_I3D_swap_frame_lock
|
||||
#endif
|
||||
|
||||
#ifndef WGL_NV_render_depth_texture
|
||||
#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3
|
||||
#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4
|
||||
#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5
|
||||
#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6
|
||||
#define WGL_DEPTH_COMPONENT_NV 0x20A7
|
||||
#endif
|
||||
|
||||
#ifndef WGL_NV_render_texture_rectangle
|
||||
#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0
|
||||
#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1
|
||||
#define WGL_TEXTURE_RECTANGLE_NV 0x20A2
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ATI_pixel_format_float
|
||||
#define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0
|
||||
#endif
|
||||
|
||||
#ifndef WGL_NV_float_buffer
|
||||
#define WGL_FLOAT_COMPONENTS_NV 0x20B0
|
||||
#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1
|
||||
#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2
|
||||
#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3
|
||||
#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4
|
||||
#define WGL_TEXTURE_FLOAT_R_NV 0x20B5
|
||||
#define WGL_TEXTURE_FLOAT_RG_NV 0x20B6
|
||||
#define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7
|
||||
#define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************/
|
||||
|
||||
#ifndef WGL_ARB_pbuffer
|
||||
DECLARE_HANDLE(HPBUFFERARB);
|
||||
#endif
|
||||
#ifndef WGL_EXT_pbuffer
|
||||
DECLARE_HANDLE(HPBUFFEREXT);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ARB_buffer_region
|
||||
#define WGL_ARB_buffer_region 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern HANDLE WINAPI wglCreateBufferRegionARB (HDC, int, UINT);
|
||||
extern VOID WINAPI wglDeleteBufferRegionARB (HANDLE);
|
||||
extern BOOL WINAPI wglSaveBufferRegionARB (HANDLE, int, int, int, int);
|
||||
extern BOOL WINAPI wglRestoreBufferRegionARB (HANDLE, int, int, int, int, int, int);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType);
|
||||
typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion);
|
||||
typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height);
|
||||
typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ARB_multisample
|
||||
#define WGL_ARB_multisample 1
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ARB_extensions_string
|
||||
#define WGL_ARB_extensions_string 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern const char * WINAPI wglGetExtensionsStringARB (HDC);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ARB_pixel_format
|
||||
#define WGL_ARB_pixel_format 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern BOOL WINAPI wglGetPixelFormatAttribivARB (HDC, int, int, UINT, const int *, int *);
|
||||
extern BOOL WINAPI wglGetPixelFormatAttribfvARB (HDC, int, int, UINT, const int *, FLOAT *);
|
||||
extern BOOL WINAPI wglChoosePixelFormatARB (HDC, const int *, const FLOAT *, UINT, int *, UINT *);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
|
||||
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);
|
||||
typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ARB_make_current_read
|
||||
#define WGL_ARB_make_current_read 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern BOOL WINAPI wglMakeContextCurrentARB (HDC, HDC, HGLRC);
|
||||
extern HDC WINAPI wglGetCurrentReadDCARB (void);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
|
||||
typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ARB_pbuffer
|
||||
#define WGL_ARB_pbuffer 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern HPBUFFERARB WINAPI wglCreatePbufferARB (HDC, int, int, int, const int *);
|
||||
extern HDC WINAPI wglGetPbufferDCARB (HPBUFFERARB);
|
||||
extern int WINAPI wglReleasePbufferDCARB (HPBUFFERARB, HDC);
|
||||
extern BOOL WINAPI wglDestroyPbufferARB (HPBUFFERARB);
|
||||
extern BOOL WINAPI wglQueryPbufferARB (HPBUFFERARB, int, int *);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
|
||||
typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer);
|
||||
typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC);
|
||||
typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer);
|
||||
typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ARB_render_texture
|
||||
#define WGL_ARB_render_texture 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern BOOL WINAPI wglBindTexImageARB (HPBUFFERARB, int);
|
||||
extern BOOL WINAPI wglReleaseTexImageARB (HPBUFFERARB, int);
|
||||
extern BOOL WINAPI wglSetPbufferAttribARB (HPBUFFERARB, const int *);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
|
||||
typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
|
||||
typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int *piAttribList);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ARB_pixel_format_float
|
||||
#define WGL_ARB_pixel_format_float 1
|
||||
#endif
|
||||
|
||||
#ifndef WGL_EXT_display_color_table
|
||||
#define WGL_EXT_display_color_table 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern GLboolean WINAPI wglCreateDisplayColorTableEXT (GLushort);
|
||||
extern GLboolean WINAPI wglLoadDisplayColorTableEXT (const GLushort *, GLuint);
|
||||
extern GLboolean WINAPI wglBindDisplayColorTableEXT (GLushort);
|
||||
extern VOID WINAPI wglDestroyDisplayColorTableEXT (GLushort);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id);
|
||||
typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (const GLushort *table, GLuint length);
|
||||
typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id);
|
||||
typedef VOID (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_EXT_extensions_string
|
||||
#define WGL_EXT_extensions_string 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern const char * WINAPI wglGetExtensionsStringEXT (void);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_EXT_make_current_read
|
||||
#define WGL_EXT_make_current_read 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern BOOL WINAPI wglMakeContextCurrentEXT (HDC, HDC, HGLRC);
|
||||
extern HDC WINAPI wglGetCurrentReadDCEXT (void);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
|
||||
typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (void);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_EXT_pbuffer
|
||||
#define WGL_EXT_pbuffer 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern HPBUFFEREXT WINAPI wglCreatePbufferEXT (HDC, int, int, int, const int *);
|
||||
extern HDC WINAPI wglGetPbufferDCEXT (HPBUFFEREXT);
|
||||
extern int WINAPI wglReleasePbufferDCEXT (HPBUFFEREXT, HDC);
|
||||
extern BOOL WINAPI wglDestroyPbufferEXT (HPBUFFEREXT);
|
||||
extern BOOL WINAPI wglQueryPbufferEXT (HPBUFFEREXT, int, int *);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
|
||||
typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer);
|
||||
typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC);
|
||||
typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer);
|
||||
typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_EXT_pixel_format
|
||||
#define WGL_EXT_pixel_format 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern BOOL WINAPI wglGetPixelFormatAttribivEXT (HDC, int, int, UINT, int *, int *);
|
||||
extern BOOL WINAPI wglGetPixelFormatAttribfvEXT (HDC, int, int, UINT, int *, FLOAT *);
|
||||
extern BOOL WINAPI wglChoosePixelFormatEXT (HDC, const int *, const FLOAT *, UINT, int *, UINT *);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues);
|
||||
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues);
|
||||
typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_EXT_swap_control
|
||||
#define WGL_EXT_swap_control 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern BOOL WINAPI wglSwapIntervalEXT (int);
|
||||
extern int WINAPI wglGetSwapIntervalEXT (void);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);
|
||||
typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_EXT_depth_float
|
||||
#define WGL_EXT_depth_float 1
|
||||
#endif
|
||||
|
||||
#ifndef WGL_NV_vertex_array_range
|
||||
#define WGL_NV_vertex_array_range 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern void* WINAPI wglAllocateMemoryNV (GLsizei, GLfloat, GLfloat, GLfloat);
|
||||
extern void WINAPI wglFreeMemoryNV (void *);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef void* (WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority);
|
||||
typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_3DFX_multisample
|
||||
#define WGL_3DFX_multisample 1
|
||||
#endif
|
||||
|
||||
#ifndef WGL_EXT_multisample
|
||||
#define WGL_EXT_multisample 1
|
||||
#endif
|
||||
|
||||
#ifndef WGL_OML_sync_control
|
||||
#define WGL_OML_sync_control 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern BOOL WINAPI wglGetSyncValuesOML (HDC, INT64 *, INT64 *, INT64 *);
|
||||
extern BOOL WINAPI wglGetMscRateOML (HDC, INT32 *, INT32 *);
|
||||
extern INT64 WINAPI wglSwapBuffersMscOML (HDC, INT64, INT64, INT64);
|
||||
extern INT64 WINAPI wglSwapLayerBuffersMscOML (HDC, int, INT64, INT64, INT64);
|
||||
extern BOOL WINAPI wglWaitForMscOML (HDC, INT64, INT64, INT64, INT64 *, INT64 *, INT64 *);
|
||||
extern BOOL WINAPI wglWaitForSbcOML (HDC, INT64, INT64 *, INT64 *, INT64 *);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc);
|
||||
typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32 *numerator, INT32 *denominator);
|
||||
typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder);
|
||||
typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder);
|
||||
typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc);
|
||||
typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_I3D_digital_video_control
|
||||
#define WGL_I3D_digital_video_control 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern BOOL WINAPI wglGetDigitalVideoParametersI3D (HDC, int, int *);
|
||||
extern BOOL WINAPI wglSetDigitalVideoParametersI3D (HDC, int, const int *);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue);
|
||||
typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_I3D_gamma
|
||||
#define WGL_I3D_gamma 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern BOOL WINAPI wglGetGammaTableParametersI3D (HDC, int, int *);
|
||||
extern BOOL WINAPI wglSetGammaTableParametersI3D (HDC, int, const int *);
|
||||
extern BOOL WINAPI wglGetGammaTableI3D (HDC, int, USHORT *, USHORT *, USHORT *);
|
||||
extern BOOL WINAPI wglSetGammaTableI3D (HDC, int, const USHORT *, const USHORT *, const USHORT *);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue);
|
||||
typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue);
|
||||
typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue);
|
||||
typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_I3D_genlock
|
||||
#define WGL_I3D_genlock 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern BOOL WINAPI wglEnableGenlockI3D (HDC);
|
||||
extern BOOL WINAPI wglDisableGenlockI3D (HDC);
|
||||
extern BOOL WINAPI wglIsEnabledGenlockI3D (HDC, BOOL *);
|
||||
extern BOOL WINAPI wglGenlockSourceI3D (HDC, UINT);
|
||||
extern BOOL WINAPI wglGetGenlockSourceI3D (HDC, UINT *);
|
||||
extern BOOL WINAPI wglGenlockSourceEdgeI3D (HDC, UINT);
|
||||
extern BOOL WINAPI wglGetGenlockSourceEdgeI3D (HDC, UINT *);
|
||||
extern BOOL WINAPI wglGenlockSampleRateI3D (HDC, UINT);
|
||||
extern BOOL WINAPI wglGetGenlockSampleRateI3D (HDC, UINT *);
|
||||
extern BOOL WINAPI wglGenlockSourceDelayI3D (HDC, UINT);
|
||||
extern BOOL WINAPI wglGetGenlockSourceDelayI3D (HDC, UINT *);
|
||||
extern BOOL WINAPI wglQueryGenlockMaxSourceDelayI3D (HDC, UINT *, UINT *);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC);
|
||||
typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC);
|
||||
typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL *pFlag);
|
||||
typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource);
|
||||
typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT *uSource);
|
||||
typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge);
|
||||
typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT *uEdge);
|
||||
typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate);
|
||||
typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT *uRate);
|
||||
typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay);
|
||||
typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT *uDelay);
|
||||
typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_I3D_image_buffer
|
||||
#define WGL_I3D_image_buffer 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern LPVOID WINAPI wglCreateImageBufferI3D (HDC, DWORD, UINT);
|
||||
extern BOOL WINAPI wglDestroyImageBufferI3D (HDC, LPVOID);
|
||||
extern BOOL WINAPI wglAssociateImageBufferEventsI3D (HDC, const HANDLE *, const LPVOID *, const DWORD *, UINT);
|
||||
extern BOOL WINAPI wglReleaseImageBufferEventsI3D (HDC, const LPVOID *, UINT);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags);
|
||||
typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress);
|
||||
typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count);
|
||||
typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const LPVOID *pAddress, UINT count);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_I3D_swap_frame_lock
|
||||
#define WGL_I3D_swap_frame_lock 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern BOOL WINAPI wglEnableFrameLockI3D (void);
|
||||
extern BOOL WINAPI wglDisableFrameLockI3D (void);
|
||||
extern BOOL WINAPI wglIsEnabledFrameLockI3D (BOOL *);
|
||||
extern BOOL WINAPI wglQueryFrameLockMasterI3D (BOOL *);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (void);
|
||||
typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (void);
|
||||
typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL *pFlag);
|
||||
typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL *pFlag);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_I3D_swap_frame_usage
|
||||
#define WGL_I3D_swap_frame_usage 1
|
||||
#ifdef WGL_WGLEXT_PROTOTYPES
|
||||
extern BOOL WINAPI wglGetFrameUsageI3D (float *);
|
||||
extern BOOL WINAPI wglBeginFrameTrackingI3D (void);
|
||||
extern BOOL WINAPI wglEndFrameTrackingI3D (void);
|
||||
extern BOOL WINAPI wglQueryFrameTrackingI3D (DWORD *, DWORD *, float *);
|
||||
#endif /* WGL_WGLEXT_PROTOTYPES */
|
||||
typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float *pUsage);
|
||||
typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void);
|
||||
typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void);
|
||||
typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage);
|
||||
#endif
|
||||
|
||||
#ifndef WGL_ATI_pixel_format_float
|
||||
#define WGL_ATI_pixel_format_float 1
|
||||
#endif
|
||||
|
||||
#ifndef WGL_NV_float_buffer
|
||||
#define WGL_NV_float_buffer 1
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
12262
oversampling/WDL/lice/glew/include/GL/glew.h
Normal file
12262
oversampling/WDL/lice/glew/include/GL/glew.h
Normal file
File diff suppressed because it is too large
Load Diff
1397
oversampling/WDL/lice/glew/include/GL/glxew.h
Normal file
1397
oversampling/WDL/lice/glew/include/GL/glxew.h
Normal file
File diff suppressed because it is too large
Load Diff
1165
oversampling/WDL/lice/glew/include/GL/wglew.h
Normal file
1165
oversampling/WDL/lice/glew/include/GL/wglew.h
Normal file
File diff suppressed because it is too large
Load Diff
12180
oversampling/WDL/lice/glew/src/glew.c
Normal file
12180
oversampling/WDL/lice/glew/src/glew.c
Normal file
File diff suppressed because it is too large
Load Diff
7180
oversampling/WDL/lice/glew/src/glewinfo.c
Normal file
7180
oversampling/WDL/lice/glew/src/glewinfo.c
Normal file
File diff suppressed because it is too large
Load Diff
1173
oversampling/WDL/lice/glew/src/visualinfo.c
Normal file
1173
oversampling/WDL/lice/glew/src/visualinfo.c
Normal file
File diff suppressed because it is too large
Load Diff
3058
oversampling/WDL/lice/lice.cpp
Normal file
3058
oversampling/WDL/lice/lice.cpp
Normal file
File diff suppressed because it is too large
Load Diff
639
oversampling/WDL/lice/lice.h
Normal file
639
oversampling/WDL/lice/lice.h
Normal file
@@ -0,0 +1,639 @@
|
||||
#ifndef _LICE_H
|
||||
#define _LICE_H
|
||||
|
||||
/*
|
||||
Cockos WDL - LICE - Lightweight Image Compositing Engine
|
||||
|
||||
Copyright (C) 2007 and later, Cockos Incorporated
|
||||
Portions Copyright (C) 2007 "schwa"
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include "../swell/swell-types.h" // use SWELL on other systems
|
||||
#endif
|
||||
|
||||
|
||||
// one of these can be defined in your project if you choose:
|
||||
//#define LICE_FAVOR_SPEED // optimizes some stuff that doesnt seem to benefit much (like LICE_DeltaBlit/LICE_RotatedBlit/LICE_TransformBlit)
|
||||
// (nothing) default probably good overall
|
||||
//#define LICE_FAVOR_SIZE // reduces code size of normal/scaled blit functions
|
||||
//#define LICE_FAVOR_SIZE_EXTREME // same as LICE_FAVOR_SIZE w/ smaller gains with bigger perf penalties (solid fills etc)
|
||||
|
||||
#ifdef LICE_FAVOR_SPEED
|
||||
#ifdef LICE_FAVOR_SIZE_EXTREME
|
||||
#undef LICE_FAVOR_SIZE_EXTREME
|
||||
#endif
|
||||
#ifdef LICE_FAVOR_SIZE
|
||||
#undef LICE_FAVOR_SIZE
|
||||
#endif
|
||||
#endif
|
||||
#if defined(LICE_FAVOR_SIZE_EXTREME) && !defined(LICE_FAVOR_SIZE)
|
||||
#define LICE_FAVOR_SIZE
|
||||
#endif
|
||||
|
||||
|
||||
typedef unsigned int LICE_pixel;
|
||||
typedef unsigned char LICE_pixel_chan;
|
||||
|
||||
#define LICE_RGBA(r,g,b,a) (((b)&0xff)|(((g)&0xff)<<8)|(((r)&0xff)<<16)|(((a)&0xff)<<24))
|
||||
#define LICE_GETB(v) ((v)&0xff)
|
||||
#define LICE_GETG(v) (((v)>>8)&0xff)
|
||||
#define LICE_GETR(v) (((v)>>16)&0xff)
|
||||
#define LICE_GETA(v) (((v)>>24)&0xff)
|
||||
|
||||
#if defined(__APPLE__) && defined(__ppc__)
|
||||
#define LICE_PIXEL_A 0
|
||||
#define LICE_PIXEL_R 1
|
||||
#define LICE_PIXEL_G 2
|
||||
#define LICE_PIXEL_B 3
|
||||
#else
|
||||
#define LICE_PIXEL_B 0
|
||||
#define LICE_PIXEL_G 1
|
||||
#define LICE_PIXEL_R 2
|
||||
#define LICE_PIXEL_A 3
|
||||
#endif
|
||||
|
||||
|
||||
static inline LICE_pixel LICE_RGBA_FROMNATIVE(LICE_pixel col, int alpha=0)
|
||||
{
|
||||
return LICE_RGBA(GetRValue(col),GetGValue(col),GetBValue(col),alpha);
|
||||
}
|
||||
|
||||
// bitmap interface, and some built-in types (memory bitmap and system bitmap)
|
||||
|
||||
class LICE_IBitmap
|
||||
{
|
||||
public:
|
||||
virtual ~LICE_IBitmap() { }
|
||||
|
||||
virtual LICE_pixel *getBits()=0;
|
||||
virtual int getWidth()=0;
|
||||
virtual int getHeight()=0;
|
||||
virtual int getRowSpan()=0; // includes any off-bitmap data
|
||||
virtual bool isFlipped() { return false; }
|
||||
virtual bool resize(int w, int h)=0;
|
||||
|
||||
virtual HDC getDC() { return 0; } // only sysbitmaps have to implement this
|
||||
|
||||
|
||||
virtual INT_PTR Extended(int id, void* data) { return 0; }
|
||||
};
|
||||
|
||||
#define LICE_EXT_SET_SCALING 0x2000 // data = int *, scaling is .8 fixed point. returns true if supported. affects LICE_*() draw operations
|
||||
#define LICE_EXT_GET_SCALING 0x2001 // data ignored, returns .8 fixed point, returns 0 if unscaled
|
||||
#define LICE_EXT_SET_ADVISORY_SCALING 0x2002 // data = int *, scaling is .8 fixed point. returns true if supported. does not affect draw operations
|
||||
#define LICE_EXT_GET_ADVISORY_SCALING 0x2003 // data ignored, returns .8 fixed point. returns 0 if unscaled
|
||||
#define LICE_EXT_GET_ANY_SCALING 0x2004 // data ignored, returns .8 fixed point, 0 if unscaled
|
||||
|
||||
#define LICE_MEMBITMAP_ALIGNAMT 63
|
||||
|
||||
class LICE_MemBitmap : public LICE_IBitmap
|
||||
{
|
||||
public:
|
||||
LICE_MemBitmap(int w=0, int h=0, unsigned int linealign=4);
|
||||
virtual ~LICE_MemBitmap();
|
||||
|
||||
|
||||
// LICE_IBitmap interface
|
||||
virtual LICE_pixel *getBits()
|
||||
{
|
||||
const UINT_PTR extra=LICE_MEMBITMAP_ALIGNAMT;
|
||||
return (LICE_pixel *) (((UINT_PTR)m_fb + extra)&~extra);
|
||||
}
|
||||
virtual int getWidth() { return m_width; }
|
||||
virtual int getHeight() { return m_height; }
|
||||
virtual int getRowSpan() { return (m_width+m_linealign)&~m_linealign; }
|
||||
virtual bool resize(int w, int h) { return __resize(w,h); } // returns TRUE if a resize occurred
|
||||
|
||||
// todo: LICE_EXT_SET_SCALING ?
|
||||
|
||||
private:
|
||||
bool __resize(int w, int h);
|
||||
LICE_pixel *m_fb;
|
||||
int m_width, m_height;
|
||||
int m_allocsize;
|
||||
unsigned int m_linealign;
|
||||
};
|
||||
|
||||
class LICE_SysBitmap : public LICE_IBitmap
|
||||
{
|
||||
public:
|
||||
LICE_SysBitmap(int w=0, int h=0);
|
||||
virtual ~LICE_SysBitmap();
|
||||
|
||||
// LICE_IBitmap interface
|
||||
virtual LICE_pixel *getBits() { return m_bits; }
|
||||
virtual int getWidth() { return m_width; }
|
||||
virtual int getHeight() { return m_height; }
|
||||
virtual int getRowSpan() { return m_allocw; };
|
||||
virtual bool resize(int w, int h) { return __resize(w,h); } // returns TRUE if a resize occurred
|
||||
|
||||
virtual INT_PTR Extended(int id, void* data)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case LICE_EXT_SET_ADVISORY_SCALING:
|
||||
{
|
||||
int sc = data && *(int*)data != 256 ? *(int *)data : 0;
|
||||
if (sc < 0) sc = 0;
|
||||
m_adv_scaling = sc;
|
||||
}
|
||||
return 1;
|
||||
case LICE_EXT_SET_SCALING:
|
||||
{
|
||||
int sc = data && *(int*)data != 256 ? *(int *)data : 0;
|
||||
if (sc < 0) sc = 0;
|
||||
if (m_draw_scaling != sc)
|
||||
{
|
||||
const int tmp=m_width;
|
||||
m_draw_scaling = sc;
|
||||
m_width=0;
|
||||
resize(tmp,m_height);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case LICE_EXT_GET_SCALING:
|
||||
return m_draw_scaling;
|
||||
case LICE_EXT_GET_ADVISORY_SCALING:
|
||||
return m_adv_scaling;
|
||||
case LICE_EXT_GET_ANY_SCALING:
|
||||
if (m_draw_scaling > 0)
|
||||
{
|
||||
if (m_adv_scaling > 0)
|
||||
return (m_adv_scaling * m_draw_scaling) >> 8;
|
||||
return m_draw_scaling;
|
||||
}
|
||||
return m_adv_scaling;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// sysbitmap specific calls
|
||||
virtual HDC getDC() { return m_dc; }
|
||||
|
||||
|
||||
private:
|
||||
bool __resize(int w, int h);
|
||||
int m_width, m_height;
|
||||
|
||||
HDC m_dc;
|
||||
LICE_pixel *m_bits;
|
||||
int m_allocw, m_alloch;
|
||||
#ifdef _WIN32
|
||||
HBITMAP m_bitmap;
|
||||
HGDIOBJ m_oldbitmap;
|
||||
#endif
|
||||
int m_draw_scaling, m_adv_scaling;
|
||||
};
|
||||
|
||||
class LICE_WrapperBitmap : public LICE_IBitmap
|
||||
{
|
||||
public:
|
||||
LICE_WrapperBitmap(LICE_pixel *buf, int w, int h, int span, bool flipped)
|
||||
{
|
||||
m_buf=buf;
|
||||
m_w=w;
|
||||
m_h=h;
|
||||
m_span=span;
|
||||
m_flipped=flipped;
|
||||
}
|
||||
virtual ~LICE_WrapperBitmap() {}
|
||||
|
||||
virtual bool resize(int w, int h) { return false; }
|
||||
virtual LICE_pixel *getBits() { return m_buf; }
|
||||
virtual int getWidth() { return m_w; }
|
||||
virtual int getHeight() { return m_h; }
|
||||
virtual int getRowSpan() { return m_span; }
|
||||
|
||||
virtual HDC getDC() { return NULL; }
|
||||
virtual bool isFlipped() { return m_flipped; }
|
||||
|
||||
|
||||
LICE_pixel *m_buf;
|
||||
int m_w,m_h,m_span;
|
||||
bool m_flipped;
|
||||
};
|
||||
|
||||
|
||||
class LICE_SubBitmap : public LICE_IBitmap // note: you should only keep these around as long as they are needed, and don't resize the parent while this is allocated
|
||||
{
|
||||
public:
|
||||
LICE_SubBitmap(LICE_IBitmap *parent, int x, int y, int w, int h)
|
||||
{
|
||||
m_parent=parent;
|
||||
if(x<0)x=0;
|
||||
if(y<0)y=0;
|
||||
m_x=x;m_y=y;
|
||||
__resize(w,h);
|
||||
}
|
||||
virtual ~LICE_SubBitmap() { }
|
||||
|
||||
virtual bool resize(int w, int h) { return __resize(w,h); }
|
||||
|
||||
bool __resize(int w, int h)
|
||||
{
|
||||
m_w=0;m_h=0;
|
||||
if (m_parent && m_x >= 0 && m_y >= 0 && m_x < m_parent->getWidth() && m_y < m_parent->getHeight())
|
||||
{
|
||||
if (w > m_parent->getWidth()-m_x) w=m_parent->getWidth()-m_x;
|
||||
if (h > m_parent->getHeight()-m_y) h=m_parent->getHeight()-m_y;
|
||||
|
||||
m_w=w;
|
||||
m_h=h;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool isFlipped() { return m_parent && m_parent->isFlipped(); }
|
||||
|
||||
virtual LICE_pixel *getBits()
|
||||
{
|
||||
if (!m_parent) return 0;
|
||||
|
||||
int xc = m_x, yc = m_y, h = m_h;
|
||||
const int scale = (int)m_parent->Extended(LICE_EXT_GET_SCALING,NULL);
|
||||
if (scale > 0)
|
||||
{
|
||||
xc = (xc*scale)>>8;
|
||||
yc = (yc*scale)>>8;
|
||||
h = (h*scale)>>8;
|
||||
}
|
||||
|
||||
LICE_pixel* parentptr=m_parent->getBits();
|
||||
if (m_parent->isFlipped()) parentptr += (m_parent->getHeight() - (yc+h))*m_parent->getRowSpan()+xc;
|
||||
else parentptr += yc*m_parent->getRowSpan()+xc;
|
||||
|
||||
return parentptr;
|
||||
}
|
||||
|
||||
enum {
|
||||
LICE_GET_SUBBITMAP_VERSION = 0x51b7000,
|
||||
LICE_SUBBITMAP_VERSION = 0x1000 // if we change any of this struct, then we *must* increment this version.
|
||||
};
|
||||
|
||||
virtual INT_PTR Extended(int id, void* data)
|
||||
{
|
||||
if (id == LICE_GET_SUBBITMAP_VERSION) return LICE_SUBBITMAP_VERSION;
|
||||
|
||||
if (!m_parent) return 0;
|
||||
return m_parent->Extended(id, data);
|
||||
}
|
||||
|
||||
virtual int getWidth() { return m_w; }
|
||||
virtual int getHeight() { return m_h; }
|
||||
virtual int getRowSpan() { return m_parent ? m_parent->getRowSpan() : 0; }
|
||||
|
||||
virtual HDC getDC() { return NULL; }
|
||||
|
||||
int m_w,m_h,m_x,m_y;
|
||||
LICE_IBitmap *m_parent;
|
||||
};
|
||||
|
||||
|
||||
// flags that most blit functions can take
|
||||
|
||||
#define LICE_BLIT_MODE_MASK 0xff
|
||||
#define LICE_BLIT_MODE_COPY 0
|
||||
#define LICE_BLIT_MODE_ADD 1
|
||||
#define LICE_BLIT_MODE_DODGE 2
|
||||
#define LICE_BLIT_MODE_MUL 3
|
||||
#define LICE_BLIT_MODE_OVERLAY 4
|
||||
#define LICE_BLIT_MODE_HSVADJ 5
|
||||
|
||||
#define LICE_BLIT_MODE_CHANCOPY 0xf0 // in this mode, only available for LICE_Blit(), the low nibble is 2 bits of source channel (low 2), 2 bits of dest channel (high 2)
|
||||
|
||||
#define LICE_BLIT_FILTER_MASK 0xff00
|
||||
#define LICE_BLIT_FILTER_NONE 0
|
||||
#define LICE_BLIT_FILTER_BILINEAR 0x100 // currently pretty slow! ack
|
||||
#define LICE_BLIT_IGNORE_SCALING 0x20000
|
||||
|
||||
|
||||
#define LICE_BLIT_USE_ALPHA 0x10000 // use source's alpha channel
|
||||
|
||||
#ifndef lice_max
|
||||
#define lice_max(x,y) ((x)<(y)?(y):(x))
|
||||
#define lice_min(x,y) ((x)<(y)?(x):(y))
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <float.h>
|
||||
#define lice_isfinite(x) _finite(x)
|
||||
#else
|
||||
#define lice_isfinite(x) isfinite(x)
|
||||
#endif
|
||||
|
||||
// Reaper exports most LICE functions, so the function declarations below
|
||||
// will collide with reaper_plugin.h
|
||||
#ifndef LICE_PROVIDED_BY_APP
|
||||
|
||||
|
||||
// bitmap loaders
|
||||
|
||||
// dispatch to a linked loader implementation based on file extension
|
||||
LICE_IBitmap* LICE_LoadImage(const char* filename, LICE_IBitmap* bmp=NULL, bool tryIgnoreExtension=false);
|
||||
char *LICE_GetImageExtensionList(bool wantAllSup=true, bool wantAllFiles=true); // returns doublenull terminated GetOpenFileName() style list -- free() when done.
|
||||
bool LICE_ImageIsSupported(const char *filename); // must be a filename that ends in .jpg, etc. if you want to check the extension, pass .ext
|
||||
|
||||
|
||||
// pass a bmp if you wish to load it into that bitmap. note that if it fails bmp will not be deleted.
|
||||
LICE_IBitmap *LICE_LoadPNG(const char *filename, LICE_IBitmap *bmp=NULL); // returns a bitmap (bmp if nonzero) on success
|
||||
LICE_IBitmap *LICE_LoadPNGFromMemory(const void *data_in, int buflen, LICE_IBitmap *bmp=NULL);
|
||||
LICE_IBitmap *LICE_LoadPNGFromResource(HINSTANCE hInst, const char *resid, LICE_IBitmap *bmp=NULL); // returns a bitmap (bmp if nonzero) on success
|
||||
#ifndef _WIN32
|
||||
LICE_IBitmap *LICE_LoadPNGFromNamedResource(const char *name, LICE_IBitmap *bmp=NULL); // returns a bitmap (bmp if nonzero) on success
|
||||
#endif
|
||||
|
||||
LICE_IBitmap *LICE_LoadBMP(const char *filename, LICE_IBitmap *bmp=NULL); // returns a bitmap (bmp if nonzero) on success
|
||||
LICE_IBitmap *LICE_LoadBMPFromResource(HINSTANCE hInst, const char *resid, LICE_IBitmap *bmp=NULL); // returns a bitmap (bmp if nonzero) on success
|
||||
|
||||
LICE_IBitmap *LICE_LoadIcon(const char *filename, int reqiconsz=16, LICE_IBitmap *bmp=NULL); // returns a bitmap (bmp if nonzero) on success
|
||||
LICE_IBitmap *LICE_LoadIconFromResource(HINSTANCE hInst, const char *resid, int reqiconsz=16, LICE_IBitmap *bmp=NULL); // returns a bitmap (bmp if nonzero) on success
|
||||
|
||||
LICE_IBitmap *LICE_LoadJPG(const char *filename, LICE_IBitmap *bmp=NULL);
|
||||
LICE_IBitmap *LICE_LoadJPGFromMemory(const void *data_in, int buflen, LICE_IBitmap *bmp = NULL);
|
||||
LICE_IBitmap* LICE_LoadJPGFromResource(HINSTANCE hInst, const char *resid, LICE_IBitmap* bmp = 0);
|
||||
|
||||
LICE_IBitmap *LICE_LoadGIF(const char *filename, LICE_IBitmap *bmp=NULL, int *nframes=NULL); // if nframes set, will be set to number of images (stacked vertically), otherwise first frame used
|
||||
|
||||
LICE_IBitmap *LICE_LoadPCX(const char *filename, LICE_IBitmap *bmp=NULL); // returns a bitmap (bmp if nonzero) on success
|
||||
|
||||
// bitmap saving
|
||||
bool LICE_WritePNG(const char *filename, LICE_IBitmap *bmp, bool wantalpha=true);
|
||||
bool LICE_WriteJPG(const char *filename, LICE_IBitmap *bmp, int quality=95, bool force_baseline=true);
|
||||
bool LICE_WriteGIF(const char *filename, LICE_IBitmap *bmp, int transparent_alpha=0, bool dither=true); // if alpha<transparent_alpha then transparent. if transparent_alpha<0, then intra-frame checking is used
|
||||
|
||||
// animated GIF API. use transparent_alpha=-1 to encode unchanged pixels as transparent
|
||||
void *LICE_WriteGIFBegin(const char *filename, LICE_IBitmap *firstframe, int transparent_alpha=0, int frame_delay=0, bool dither=true, int nreps=0); // nreps=0 for infinite
|
||||
void *LICE_WriteGIFBeginNoFrame(const char *filename, int w, int h, int transparent_alpha=0, bool dither=true, bool is_append=false);
|
||||
bool LICE_WriteGIFFrame(void *handle, LICE_IBitmap *frame, int xpos, int ypos, bool perImageColorMap=false, int frame_delay=0, int nreps=0); // nreps only used on the first frame, 0=infinite
|
||||
unsigned int LICE_WriteGIFGetSize(void *handle); // gets current output size
|
||||
bool LICE_WriteGIFEnd(void *handle);
|
||||
int LICE_SetGIFColorMapFromOctree(void *wr, void *octree, int numcolors); // can use after LICE_WriteGIFBeginNoFrame and before LICE_WriteGIFFrame
|
||||
|
||||
// animated GIF reading
|
||||
void *LICE_GIF_LoadEx(const char *filename);
|
||||
void LICE_GIF_Close(void *handle);
|
||||
void LICE_GIF_Rewind(void *handle);
|
||||
unsigned int LICE_GIF_GetFilePos(void *handle); // gets current read position
|
||||
int LICE_GIF_UpdateFrame(void *handle, LICE_IBitmap *bm); // returns duration in msec (0 or more), or <0 if no more frames. bm will be modified/resized with new frame data
|
||||
|
||||
|
||||
|
||||
// basic primitives
|
||||
void LICE_PutPixel(LICE_IBitmap *bm, int x, int y, LICE_pixel color, float alpha, int mode);
|
||||
LICE_pixel LICE_GetPixel(LICE_IBitmap *bm, int x, int y);
|
||||
|
||||
// blit functions
|
||||
|
||||
void LICE_Copy(LICE_IBitmap *dest, LICE_IBitmap *src); // resizes dest to fit
|
||||
|
||||
|
||||
//alpha parameter = const alpha (combined with source alpha if spcified)
|
||||
void LICE_Blit(LICE_IBitmap *dest, LICE_IBitmap *src, int dstx, int dsty, const RECT *srcrect, float alpha, int mode);
|
||||
void LICE_Blit(LICE_IBitmap *dest, LICE_IBitmap *src, int dstx, int dsty, int srcx, int srcy, int srcw, int srch, float alpha, int mode);
|
||||
|
||||
void LICE_Blur(LICE_IBitmap *dest, LICE_IBitmap *src, int dstx, int dsty, int srcx, int srcy, int srcw, int srch);
|
||||
|
||||
// dstw/dsty can be negative, srcw/srch can be as well (for flipping)
|
||||
void LICE_ScaledBlit(LICE_IBitmap *dest, LICE_IBitmap *src, int dstx, int dsty, int dstw, int dsth,
|
||||
float srcx, float srcy, float srcw, float srch, float alpha, int mode);
|
||||
|
||||
|
||||
void LICE_HalveBlitAA(LICE_IBitmap *dest, LICE_IBitmap *src); // AA's src down to dest. uses the minimum size of both (use with LICE_SubBitmap to do sections)
|
||||
|
||||
// if cliptosourcerect is false, then areas outside the source rect can get in (otherwise they are not drawn)
|
||||
void LICE_RotatedBlit(LICE_IBitmap *dest, LICE_IBitmap *src,
|
||||
int dstx, int dsty, int dstw, int dsth,
|
||||
float srcx, float srcy, float srcw, float srch,
|
||||
float angle,
|
||||
bool cliptosourcerect, float alpha, int mode,
|
||||
float rotxcent=0.0, float rotycent=0.0); // these coordinates are offset from the center of the image, in source pixel coordinates
|
||||
|
||||
|
||||
void LICE_TransformBlit(LICE_IBitmap *dest, LICE_IBitmap *src,
|
||||
int dstx, int dsty, int dstw, int dsth,
|
||||
const float *srcpoints, int div_w, int div_h, // srcpoints coords should be div_w*div_h*2 long, and be in source image coordinates
|
||||
float alpha, int mode);
|
||||
void LICE_TransformBlit2(LICE_IBitmap *dest, LICE_IBitmap *src,
|
||||
int dstx, int dsty, int dstw, int dsth,
|
||||
const double *srcpoints, int div_w, int div_h, // srcpoints coords should be div_w*div_h*2 long, and be in source image coordinates
|
||||
float alpha, int mode);
|
||||
|
||||
void LICE_TransformBlit2Alpha(LICE_IBitmap *dest, LICE_IBitmap *src,
|
||||
int dstx, int dsty, int dstw, int dsth,
|
||||
const double *srcpoints, int div_w, int div_h, // srcpoints coords should be div_w*div_h*3 long, and be in source image coordinates + alpha
|
||||
int mode);
|
||||
|
||||
// if cliptosourcerect is false, then areas outside the source rect can get in (otherwise they are not drawn)
|
||||
void LICE_DeltaBlit(LICE_IBitmap *dest, LICE_IBitmap *src,
|
||||
int dstx, int dsty, int dstw, int dsth,
|
||||
float srcx, float srcy, float srcw, float srch,
|
||||
double dsdx, double dtdx, double dsdy, double dtdy,
|
||||
double dsdxdy, double dtdxdy,
|
||||
bool cliptosourcerect, float alpha, int mode);
|
||||
|
||||
void LICE_DeltaBlitAlpha(LICE_IBitmap *dest, LICE_IBitmap *src,
|
||||
int dstx, int dsty, int dstw, int dsth,
|
||||
float srcx, float srcy, float srcw, float srch,
|
||||
double dsdx, double dtdx, double dsdy, double dtdy,
|
||||
double dsdxdy, double dtdxdy,
|
||||
bool cliptosourcerect, float alpha, int mode, double dadx, double dady, double dadxdy);
|
||||
|
||||
|
||||
// only LICE_BLIT_MODE_ADD or LICE_BLIT_MODE_COPY are used by this, for flags
|
||||
// ir-ia should be 0.0..1.0 (or outside that and they'll be clamped)
|
||||
// drdx should be X/dstw, drdy X/dsth etc
|
||||
void LICE_GradRect(LICE_IBitmap *dest, int dstx, int dsty, int dstw, int dsth,
|
||||
float ir, float ig, float ib, float ia,
|
||||
float drdx, float dgdx, float dbdx, float dadx,
|
||||
float drdy, float dgdy, float dbdy, float dady,
|
||||
int mode);
|
||||
|
||||
void LICE_FillRect(LICE_IBitmap *dest, int x, int y, int w, int h, LICE_pixel color, float alpha = 1.0f, int mode = 0);
|
||||
void LICE_ProcessRect(LICE_IBitmap *dest, int x, int y, int w, int h, void (*procFunc)(LICE_pixel *p, void *parm), void *parm);
|
||||
|
||||
void LICE_Clear(LICE_IBitmap *dest, LICE_pixel color);
|
||||
void LICE_ClearRect(LICE_IBitmap *dest, int x, int y, int w, int h, LICE_pixel mask=0, LICE_pixel orbits=0);
|
||||
void LICE_MultiplyAddRect(LICE_IBitmap *dest, int x, int y, int w, int h,
|
||||
float rsc, float gsc, float bsc, float asc, // 0-1, or -100 .. +100 if you really are insane
|
||||
float radd, float gadd, float badd, float aadd); // 0-255 is the normal range on these.. of course its clamped
|
||||
|
||||
void LICE_SetAlphaFromColorMask(LICE_IBitmap *dest, LICE_pixel color);
|
||||
|
||||
|
||||
// non-flood fill. simply scans up/down and left/right
|
||||
void LICE_SimpleFill(LICE_IBitmap *dest, int x, int y, LICE_pixel newcolor,
|
||||
LICE_pixel comparemask=LICE_RGBA(255,255,255,0),
|
||||
LICE_pixel keepmask=LICE_RGBA(0,0,0,0));
|
||||
|
||||
|
||||
// texture generators
|
||||
void LICE_TexGen_Marble(LICE_IBitmap *dest, const RECT *rect, float rv, float gv, float bv, float intensity); //fills whole bitmap if rect == NULL
|
||||
|
||||
//this function generates a Perlin noise
|
||||
//fills whole bitmap if rect == NULL
|
||||
//smooth needs to be a multiple of 2
|
||||
enum
|
||||
{
|
||||
NOISE_MODE_NORMAL = 0,
|
||||
NOISE_MODE_WOOD,
|
||||
};
|
||||
void LICE_TexGen_Noise(LICE_IBitmap *dest, const RECT *rect, float rv, float gv, float bv, float intensity, int mode=NOISE_MODE_NORMAL, int smooth=1);
|
||||
|
||||
//this function generates a Perlin noise in a circular fashion
|
||||
//fills whole bitmap if rect == NULL
|
||||
//size needs to be a multiple of 2
|
||||
void LICE_TexGen_CircNoise(LICE_IBitmap *dest, const RECT *rect, float rv, float gv, float bv, float nrings, float power, int size);
|
||||
|
||||
|
||||
// bitmapped text drawing:
|
||||
void LICE_DrawChar(LICE_IBitmap *bm, int x, int y, char c,
|
||||
LICE_pixel color, float alpha, int mode);
|
||||
void LICE_DrawText(LICE_IBitmap *bm, int x, int y, const char *string,
|
||||
LICE_pixel color, float alpha, int mode);
|
||||
void LICE_MeasureText(const char *string, int *w, int *h);
|
||||
|
||||
// line drawing functions
|
||||
|
||||
void LICE_Line(LICE_IBitmap *dest, int x1, int y1, int x2, int y2, LICE_pixel color, float alpha=1.0f, int mode=0, bool aa=true);
|
||||
void LICE_FLine(LICE_IBitmap* dest, float x1, float y1, float x2, float y2, LICE_pixel color, float alpha=1.0f, int mode=0, bool aa=true);
|
||||
void LICE_ThickFLine(LICE_IBitmap* dest, double x1, double y1, double x2, double y2, LICE_pixel color, float alpha, int mode, int wid); // always AA. wid is not affected by scaling (1 is always normal line, 2 is always 2 physical pixels, etc)
|
||||
|
||||
void LICE_DashedLine(LICE_IBitmap* dest, int x1, int y1, int x2, int y2, int pxon, int pxoff, LICE_pixel color, float alpha=1.0f, int mode=0, bool aa=false); // straight lines only for now
|
||||
|
||||
void LICE_FillTrapezoidF(LICE_IBitmap* dest, double fx1a, double fx1b, int y1, double fx2a, double fx2b, int y2, LICE_pixel color, float alpha, int mode);
|
||||
void LICE_FillTrapezoid(LICE_IBitmap* dest, int x1a, int x1b, int y1, int x2a, int x2b, int y2, LICE_pixel color, float alpha, int mode);
|
||||
void LICE_FillConvexPolygon(LICE_IBitmap* dest, const int* x, const int* y, int npoints, LICE_pixel color, float alpha, int mode);
|
||||
|
||||
void LICE_FillTriangle(LICE_IBitmap *dest, int x1, int y1, int x2, int y2, int x3, int y3, LICE_pixel color, float alpha=1.0f, int mode=0);
|
||||
|
||||
|
||||
// Returns false if the line is entirely offscreen.
|
||||
bool LICE_ClipLine(int* pX1, int* pY1, int* pX2, int* pY2, int xLo, int yLo, int xHi, int yHi);
|
||||
bool LICE_ClipFLine(float* px1, float* py1, float* px2, float* py2, float xlo, float ylo, float xhi, float yhi);
|
||||
|
||||
void LICE_Arc(LICE_IBitmap* dest, float cx, float cy, float r, float minAngle, float maxAngle,
|
||||
LICE_pixel color, float alpha=1.0f, int mode=0, bool aa=true);
|
||||
void LICE_Circle(LICE_IBitmap* dest, float cx, float cy, float r, LICE_pixel color, float alpha=1.0f, int mode=0, bool aa=true);
|
||||
void LICE_FillCircle(LICE_IBitmap* dest, float cx, float cy, float r, LICE_pixel color, float alpha=1.0f, int mode=0, bool aa=true);
|
||||
void LICE_RoundRect(LICE_IBitmap *drawbm, float xpos, float ypos, float w, float h, int cornerradius,
|
||||
LICE_pixel col, float alpha, int mode, bool aa);
|
||||
|
||||
// useful for drawing shapes from a cache
|
||||
void LICE_DrawGlyph(LICE_IBitmap* dest, int x, int y, LICE_pixel color, const LICE_pixel_chan* alphas, int glyph_w, int glyph_h, float alpha=1.0f, int mode = 0);
|
||||
void LICE_DrawGlyphEx(LICE_IBitmap* dest, int x, int y, LICE_pixel color, const LICE_pixel_chan* alphas, int glyph_w, int glyph_span, int glyph_h, float alpha=1.0f, int mode = 0);
|
||||
|
||||
void LICE_DrawMonoGlyph(LICE_IBitmap* dest, int x, int y, LICE_pixel color, const unsigned char* alphas, int glyph_w, int glyph_span, int glyph_h, float alpha=1.0f, int mode = 0);
|
||||
|
||||
// quadratic bezier
|
||||
// tol means try to draw segments no longer than tol px
|
||||
void LICE_DrawQBezier(LICE_IBitmap* dest, double xstart, double ystart, double xctl, double yctl, double xend, double yend,
|
||||
LICE_pixel color, float alpha=1.0f, int mode=0, bool aa=true, double tol=0.0);
|
||||
|
||||
// cubic bezier
|
||||
// tol means try to draw segments no longer than tol px
|
||||
void LICE_DrawCBezier(LICE_IBitmap* dest, double xstart, double ystart, double xctl1, double yctl1,
|
||||
double xctl2, double yctl2, double xend, double yend, LICE_pixel color, float alpha=1.0f, int mode=0, bool aa=true, double tol=0.0);
|
||||
|
||||
void LICE_DrawThickCBezier(LICE_IBitmap* dest, double xstart, double ystart, double xctl1, double yctl1,
|
||||
double xctl2, double yctl2, double xend, double yend, LICE_pixel color, float alpha=1.0f, int mode=0, int wid=2, double tol=0.0);
|
||||
|
||||
// vertical fill from y=yfill
|
||||
void LICE_FillCBezier(LICE_IBitmap* dest, double xstart, double ystart, double xctl1, double yctl1,
|
||||
double xctl2, double yctl2, double xend, double yend, int yfill, LICE_pixel color, float alpha=1.0f, int mode=0, double tol=0.0);
|
||||
// horizontal fill from x=xfill
|
||||
void LICE_FillCBezierX(LICE_IBitmap* dest, double xstart, double ystart, double xctl1, double yctl1,
|
||||
double xctl2, double yctl2, double xend, double yend, int xfill, LICE_pixel color, float alpha=1.0f, int mode=0, double tol=0.0);
|
||||
|
||||
// convenience functions
|
||||
void LICE_DrawRect(LICE_IBitmap *dest, int x, int y, int w, int h, LICE_pixel color, float alpha=1.0f, int mode=0);
|
||||
void LICE_BorderedRect(LICE_IBitmap *dest, int x, int y, int w, int h, LICE_pixel bgcolor, LICE_pixel fgcolor, float alpha=1.0f, int mode=0);
|
||||
|
||||
// bitmap compare-by-value function
|
||||
int LICE_BitmapCmp(LICE_IBitmap* a, LICE_IBitmap* b, int *coordsOut=NULL);
|
||||
int LICE_BitmapCmpEx(LICE_IBitmap* a, LICE_IBitmap* b, LICE_pixel mask, int *coordsOut=NULL);
|
||||
|
||||
// colorspace functions
|
||||
void LICE_RGB2HSV(int r, int g, int b, int* h, int* s, int* v); // rgb, sv: [0,256), h: [0,384)
|
||||
void LICE_HSV2RGB(int h, int s, int v, int* r, int* g, int* b); // rgb, sv: [0,256), h: [0,384)
|
||||
LICE_pixel LICE_HSV2Pix(int h, int s, int v, int alpha); // sv: [0,256), h: [0,384)
|
||||
|
||||
LICE_pixel LICE_AlterColorHSV(LICE_pixel color, float d_hue, float d_saturation, float d_value); // hue is rolled over, saturation and value are clamped, all 0..1
|
||||
void LICE_AlterBitmapHSV(LICE_IBitmap* src, float d_hue, float d_saturation, float d_value); // hue is rolled over, saturation and value are clamped, all 0..1
|
||||
void LICE_AlterRectHSV(LICE_IBitmap* src, int x, int y, int w, int h, float d_hue, float d_saturation, float d_value, int mode=0); // hue is rolled over, saturation and value are clamped, all 0..1. mode only used for scaling disable
|
||||
|
||||
LICE_pixel LICE_CombinePixels(LICE_pixel dest, LICE_pixel src, float alpha, int mode);
|
||||
|
||||
void LICE_CombinePixels2(LICE_pixel *destptr, int r, int g, int b, int a, int ia, int mode); // does not clamp
|
||||
void LICE_CombinePixels2Clamp(LICE_pixel *destptr, int r, int g, int b, int a, int ia, int mode);
|
||||
|
||||
//// LVG
|
||||
|
||||
class ProjectStateContext;
|
||||
void *LICE_LoadLVG(const char *filename);
|
||||
void *LICE_LoadLVGFromContext(ProjectStateContext *ctx, const char *nameInfo=NULL, int defw=0, int defh=0);
|
||||
void *LICE_GetSubLVG(void *lvg, const char *subname);
|
||||
LICE_IBitmap *LICE_RenderLVG(void *lvg, int reqw=0, int reqh=0, LICE_IBitmap *useBM=NULL);
|
||||
void LICE_DestroyLVG(void *lvg);
|
||||
|
||||
/// palette
|
||||
|
||||
void* LICE_CreateOctree(int maxcolors);
|
||||
void LICE_DestroyOctree(void* octree);
|
||||
void LICE_ResetOctree(void *octree, int maxcolors); // resets back to stock, but with spares (to avoid mallocs)
|
||||
int LICE_BuildOctree(void* octree, LICE_IBitmap* bmp);
|
||||
int LICE_BuildOctreeForAlpha(void* octree, LICE_IBitmap* bmp, unsigned int minalpha);
|
||||
int LICE_BuildOctreeForDiff(void* octree, LICE_IBitmap* bmp, LICE_IBitmap* refbmp, LICE_pixel mask=LICE_RGBA(255,255,255,0));
|
||||
int LICE_FindInOctree(void* octree, LICE_pixel color);
|
||||
int LICE_ExtractOctreePalette(void* octree, LICE_pixel* palette);
|
||||
|
||||
// wrapper
|
||||
int LICE_BuildPalette(LICE_IBitmap* bmp, LICE_pixel* palette, int maxcolors);
|
||||
void LICE_TestPalette(LICE_IBitmap* bmp, LICE_pixel* palette, int numcolors);
|
||||
|
||||
|
||||
struct _LICE_ImageLoader_rec
|
||||
{
|
||||
LICE_IBitmap *(*loadfunc)(const char *filename, bool checkFileName, LICE_IBitmap *bmpbase);
|
||||
const char *(*get_extlist)(); // returns GetOpenFileName sort of list "JPEG files (*.jpg)\0*.jpg\0"
|
||||
|
||||
struct _LICE_ImageLoader_rec *_next;
|
||||
};
|
||||
extern _LICE_ImageLoader_rec *LICE_ImageLoader_list;
|
||||
|
||||
|
||||
#endif // LICE_PROVIDED_BY_APP
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define LICE_Scale_BitBlt(hdc, x,y,w,h, src, sx,sy, mode) do { \
|
||||
const int _x=(x), _y=(y), _w=(w), _h=(h), _sx = (sx), _sy = (sy), _mode=(mode); \
|
||||
const int rsc = (int) (src)->Extended(LICE_EXT_GET_SCALING,NULL); \
|
||||
if (rsc>0) \
|
||||
StretchBlt(hdc,_x,_y,_w,_h,(src)->getDC(),(_sx*rsc)/256,(_sy*rsc)/256,(_w*rsc)>>8,(_h*rsc)>>8,_mode); \
|
||||
else BitBlt(hdc,_x,_y,_w,_h,(src)->getDC(),_sx,_sy,_mode); \
|
||||
} while (0)
|
||||
#else
|
||||
#define LICE_Scale_BitBlt(hdc, x,y,w,h, src, sx,sy, mode) BitBlt(hdc,x,y,w,h,(src)->getDC(),sx,sy,mode)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
731
oversampling/WDL/lice/lice_arc.cpp
Normal file
731
oversampling/WDL/lice/lice_arc.cpp
Normal file
@@ -0,0 +1,731 @@
|
||||
#ifndef WDL_NO_DEFINE_MINMAX
|
||||
#define WDL_NO_DEFINE_MINMAX
|
||||
#endif
|
||||
#include "lice.h"
|
||||
#include "lice_combine.h"
|
||||
#include <math.h>
|
||||
|
||||
#define _PI 3.141592653589793238f
|
||||
|
||||
#define IGNORE_SCALING(mode) ((mode)&LICE_BLIT_IGNORE_SCALING)
|
||||
template <class T> inline void _SWAP(T& a, T& b) { T tmp = a; a = b; b = tmp; }
|
||||
|
||||
#define A(x) ((LICE_pixel_chan)((x)*255.0+0.5))
|
||||
#define AF(x) (255)
|
||||
|
||||
#define DEF_ALPHAS(dim) \
|
||||
static const LICE_pixel_chan alphas_unfill[] = { __ALPHAS__(A) }; \
|
||||
static const LICE_pixel_chan alphas_fill[] = { __ALPHAS__(AF) }; \
|
||||
const LICE_pixel_chan * const alphas = fill ? alphas_fill : alphas_unfill; \
|
||||
((void)sizeof(char[1 - 2*(sizeof(alphas_unfill) != dim*dim)])); \
|
||||
((void)sizeof(char[1 - 2*(sizeof(alphas_fill) != dim*dim)]));
|
||||
|
||||
static bool CachedCircle(LICE_IBitmap* dest, float cx, float cy, float r, LICE_pixel color, float alpha, int mode, bool aa, bool fill)
|
||||
{
|
||||
// fast draw for some small circles
|
||||
if (r == 1.5f)
|
||||
{
|
||||
if (aa)
|
||||
{
|
||||
#define __ALPHAS__(B) \
|
||||
A(0.31), A(1.00), A(1.00), A(0.31), \
|
||||
A(1.00), B(0.06), B(0.06), A(1.00), \
|
||||
A(1.00), B(0.06), B(0.06), A(1.00), \
|
||||
A(0.31), A(1.00), A(1.00), A(0.31),
|
||||
|
||||
DEF_ALPHAS(4)
|
||||
#undef __ALPHAS__
|
||||
LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 4, 4, alpha, mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
#define __ALPHAS__(B) \
|
||||
A(0.00), A(1.00), A(1.00), A(0.00), \
|
||||
A(1.00), B(0.00), B(0.00), A(1.00), \
|
||||
A(1.00), B(0.00), B(0.00), A(1.00), \
|
||||
A(0.00), A(1.00), A(1.00), A(0.00),
|
||||
|
||||
DEF_ALPHAS(4)
|
||||
#undef __ALPHAS__
|
||||
LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 4, 4, alpha, mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (r == 2.0f)
|
||||
{
|
||||
if (aa)
|
||||
{
|
||||
#define __ALPHAS__(B) \
|
||||
A(0.06), A(0.75), A(1.00), A(0.75), A(0.06), \
|
||||
A(0.75), A(0.82), B(0.31), A(0.82), A(0.75), \
|
||||
A(1.00), B(0.31), B(0.00), B(0.31), A(1.00), \
|
||||
A(0.75), A(0.82), B(0.31), A(0.82), A(0.75), \
|
||||
A(0.06), A(0.75), A(1.00), A(0.75), A(0.06)
|
||||
|
||||
DEF_ALPHAS(5)
|
||||
#undef __ALPHAS__
|
||||
LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 5, 5, alpha, mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
#define __ALPHAS__(B) \
|
||||
A(0.00), A(0.00), A(1.00), A(0.00), A(0.00), \
|
||||
A(0.00), A(1.00), B(0.00), A(1.00), A(0.00), \
|
||||
A(1.00), B(0.00), B(0.00), B(0.00), A(1.00), \
|
||||
A(0.00), A(1.00), B(0.00), A(1.00), A(0.00), \
|
||||
A(0.00), A(0.00), A(1.00), A(0.00), A(0.00)
|
||||
|
||||
DEF_ALPHAS(5)
|
||||
#undef __ALPHAS__
|
||||
LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 5, 5, alpha, mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (r == 2.5f) {
|
||||
if (aa) {
|
||||
#define __ALPHAS__(B) \
|
||||
A(0.06), A(0.75), A(1.00), A(1.00), A(0.75), A(0.06), \
|
||||
A(0.75), A(0.82), B(0.31), B(0.31), A(0.82), A(0.75), \
|
||||
A(1.00), B(0.31), B(0.00), B(0.00), B(0.31), A(1.00), \
|
||||
A(1.00), B(0.31), B(0.00), B(0.00), B(0.31), A(1.00), \
|
||||
A(0.75), A(0.82), B(0.31), B(0.31), A(0.82), A(0.75), \
|
||||
A(0.06), A(0.75), A(1.00), A(1.00), A(0.75), A(0.06)
|
||||
|
||||
DEF_ALPHAS(6)
|
||||
#undef __ALPHAS__
|
||||
LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 6, 6, alpha, mode);
|
||||
}
|
||||
else {
|
||||
#define __ALPHAS__(B) \
|
||||
A(0.00), A(0.00), A(1.00), A(1.00), A(0.00), A(0.00), \
|
||||
A(0.00), A(1.00), B(0.00), B(0.00), A(1.00), A(0.00), \
|
||||
A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \
|
||||
A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \
|
||||
A(0.00), A(1.00), B(0.00), B(0.00), A(1.00), A(0.00), \
|
||||
A(0.00), A(0.00), A(1.00), A(1.00), A(0.00), A(0.00)
|
||||
|
||||
DEF_ALPHAS(6)
|
||||
#undef __ALPHAS__
|
||||
LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 6, 6, alpha, mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (r == 3.0f) {
|
||||
if (aa) {
|
||||
#define __ALPHAS__(B) \
|
||||
A(0.00), A(0.56), A(1.00), A(1.00), A(1.00), A(0.56), A(0.00), \
|
||||
A(0.56), A(1.00), B(0.38), B(0.25), B(0.38), A(1.00), A(0.56), \
|
||||
A(1.00), B(0.44), B(0.00), B(0.00), B(0.00), B(0.44), A(1.00), \
|
||||
A(1.00), B(0.19), B(0.00), B(0.00), B(0.00), B(0.19), A(1.00), \
|
||||
A(1.00), B(0.44), B(0.00), B(0.00), B(0.00), B(0.44), A(1.00), \
|
||||
A(0.56), A(1.00), B(0.38), B(0.25), B(0.38), A(1.00), A(0.56), \
|
||||
A(0.00), A(0.56), A(1.00), A(1.00), A(1.00), A(0.56), A(0.00)
|
||||
|
||||
DEF_ALPHAS(7)
|
||||
#undef __ALPHAS__
|
||||
LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 7, 7, alpha, mode);
|
||||
}
|
||||
else {
|
||||
#define __ALPHAS__(B) \
|
||||
A(0.00), A(0.00), A(1.00), A(1.00), A(1.00), A(0.00), A(0.00), \
|
||||
A(0.00), A(1.00), B(0.00), B(0.00), B(0.00), A(1.00), A(0.00), \
|
||||
A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \
|
||||
A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \
|
||||
A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \
|
||||
A(0.00), A(1.00), B(0.00), B(0.00), B(0.00), A(1.00), A(0.00), \
|
||||
A(0.00), A(0.00), A(1.00), A(1.00), A(1.00), A(0.00), A(0.00)
|
||||
|
||||
DEF_ALPHAS(7)
|
||||
#undef __ALPHAS__
|
||||
LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 7, 7, alpha, mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (r == 3.5f) {
|
||||
if (aa) {
|
||||
#define __ALPHAS__(B) \
|
||||
A(0.00), A(0.31), A(0.87), A(1.00), A(1.00), A(0.87), A(0.31), A(0.00), \
|
||||
A(0.31), A(1.00), A(0.69), B(0.25), B(0.25), A(0.69), A(1.00), A(0.31), \
|
||||
A(0.87), A(0.69), B(0.00), B(0.00), B(0.00), B(0.00), A(0.69), A(0.87), \
|
||||
A(1.00), B(0.25), B(0.00), B(0.00), B(0.00), B(0.00), B(0.25), A(1.00), \
|
||||
A(1.00), B(0.25), B(0.00), B(0.00), B(0.00), B(0.00), B(0.25), A(1.00), \
|
||||
A(0.87), A(0.69), B(0.00), B(0.00), B(0.00), B(0.00), A(0.69), A(0.87), \
|
||||
A(0.31), A(1.00), A(0.69), B(0.25), B(0.25), A(0.69), A(1.00), A(0.31), \
|
||||
A(0.00), A(0.31), A(0.87), A(1.00), A(1.00), A(0.87), A(0.31), A(0.00)
|
||||
|
||||
DEF_ALPHAS(8)
|
||||
#undef __ALPHAS__
|
||||
LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 8, 8, alpha, mode);
|
||||
}
|
||||
else {
|
||||
#define __ALPHAS__(B) \
|
||||
A(0.00), A(0.00), A(1.00), A(1.00), A(1.00), A(1.00), A(0.00), A(0.00), \
|
||||
A(0.00), A(1.00), A(1.00), B(0.00), B(0.00), A(1.00), A(1.00), A(0.00), \
|
||||
A(1.00), A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), A(1.00), \
|
||||
A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \
|
||||
A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \
|
||||
A(1.00), A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), A(1.00), \
|
||||
A(0.00), A(1.00), A(1.00), B(0.00), B(0.00), A(1.00), A(1.00), A(0.00), \
|
||||
A(0.00), A(0.00), A(1.00), A(1.00), A(1.00), A(1.00), A(0.00), A(0.00)
|
||||
|
||||
DEF_ALPHAS(8)
|
||||
#undef __ALPHAS__
|
||||
LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 8, 8, alpha, mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (r == 4.0f) {
|
||||
if (aa) {
|
||||
#define __ALPHAS__(B) \
|
||||
A(0.00), A(0.12), A(0.69), A(1.00), A(1.00), A(1.00), A(0.69), A(0.12), A(0.00), \
|
||||
A(0.12), A(0.94), A(0.82), B(0.31), B(0.25), B(0.31), A(0.82), A(0.94), A(0.12), \
|
||||
A(0.69), A(0.82), B(0.06), B(0.00), B(0.00), B(0.00), B(0.06), A(0.82), A(0.69), \
|
||||
A(1.00), B(0.31), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.31), A(1.00), \
|
||||
A(1.00), B(0.19), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.19), A(1.00), \
|
||||
A(1.00), B(0.31), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.31), A(1.00), \
|
||||
A(0.69), A(0.82), B(0.06), B(0.00), B(0.00), B(0.00), B(0.06), A(0.82), A(0.69), \
|
||||
A(0.12), A(0.94), A(0.82), B(0.31), B(0.25), B(0.31), A(0.82), A(0.94), A(0.12), \
|
||||
A(0.00), A(0.12), A(0.69), A(1.00), A(1.00), A(1.00), A(0.69), A(0.12), A(0.00)
|
||||
|
||||
DEF_ALPHAS(9)
|
||||
#undef __ALPHAS__
|
||||
LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 9, 9, alpha, mode);
|
||||
}
|
||||
else {
|
||||
#define __ALPHAS__(B) \
|
||||
A(0.00), A(0.00), A(1.00), A(1.00), A(1.00), A(1.00), A(1.00), A(0.00), A(0.00), \
|
||||
A(0.00), A(1.00), A(1.00), B(0.00), B(0.00), B(0.00), A(1.00), A(1.00), A(0.00), \
|
||||
A(1.00), A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), A(1.00), \
|
||||
A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \
|
||||
A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \
|
||||
A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \
|
||||
A(1.00), A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), A(1.00), \
|
||||
A(0.00), A(1.00), A(1.00), B(0.00), B(0.00), B(0.00), A(1.00), A(1.00), A(0.00), \
|
||||
A(0.00), A(0.00), A(1.00), A(1.00), A(1.00), A(1.00), A(1.00), A(0.00), A(0.00)
|
||||
|
||||
DEF_ALPHAS(9)
|
||||
#undef __ALPHAS__
|
||||
LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 9, 9, alpha, mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (r == 5.0f)
|
||||
{
|
||||
if (aa) {
|
||||
#define __ALPHAS__(B) \
|
||||
A(0.00), A(0.00), A(0.00), A(0.58), A(0.90), A(1.00), A(0.90), A(0.58), A(0.00), A(0.00), A(0.00), \
|
||||
A(0.00), A(0.00), A(1.00), B(0.42), B(0.10), B(0.00), B(0.10), B(0.42), A(1.00), A(0.00), A(0.00), \
|
||||
A(0.00), A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), A(0.00), \
|
||||
A(0.58), B(0.42), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.42), A(0.58), \
|
||||
A(0.90), B(0.10), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.10), A(0.90), \
|
||||
A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \
|
||||
A(0.90), B(0.10), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.10), A(0.90), \
|
||||
A(0.58), B(0.42), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.42), A(0.58), \
|
||||
A(0.00), A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), A(0.00), \
|
||||
A(0.00), A(0.00), A(1.00), B(0.42), B(0.10), B(0.00), B(0.10), B(0.42), A(1.00), A(0.00), A(0.00), \
|
||||
A(0.00), A(0.00), A(0.00), A(0.58), A(0.90), A(1.00), A(0.90), A(0.58), A(0.00), A(0.00), A(0.00)
|
||||
|
||||
DEF_ALPHAS(11)
|
||||
#undef __ALPHAS__
|
||||
LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 11, 11, alpha, mode);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (r == 6.0f)
|
||||
{
|
||||
if (aa) {
|
||||
#define __ALPHAS__(B) \
|
||||
A(0.00), A(0.00), A(0.00), A(0.20), A(0.66), A(0.92), A(1.00), A(0.92), A(0.66), A(0.20), A(0.00), A(0.00), A(0.00), \
|
||||
A(0.00), A(0.00), A(0.47), A(0.81), B(0.35), B(0.09), B(0.00), B(0.09), B(0.35), A(0.81), A(0.47), A(0.00), A(0.00), \
|
||||
A(0.00), A(0.47), B(0.53), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.53), A(0.47), A(0.00), \
|
||||
A(0.20), A(0.81), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(0.81), A(0.20), \
|
||||
A(0.66), B(0.35), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.35), A(0.66), \
|
||||
A(0.92), B(0.09), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.09), A(0.92), \
|
||||
A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \
|
||||
A(0.92), B(0.09), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.09), A(0.92), \
|
||||
A(0.66), B(0.35), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.35), A(0.66), \
|
||||
A(0.20), A(0.81), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(0.81), A(0.20), \
|
||||
A(0.00), A(0.47), B(0.53), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.53), A(0.47), A(0.00), \
|
||||
A(0.00), A(0.00), A(0.47), A(0.81), B(0.35), B(0.09), B(0.00), B(0.09), B(0.35), A(0.81), A(0.47), A(0.00), A(0.00), \
|
||||
A(0.00), A(0.00), A(0.00), A(0.20), A(0.66), A(0.92), A(1.00), A(0.92), A(0.66), A(0.20), A(0.00), A(0.00), A(0.00),
|
||||
|
||||
DEF_ALPHAS(13)
|
||||
#undef __ALPHAS__
|
||||
LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 13, 13, alpha, mode);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (r == 7.0f)
|
||||
{
|
||||
if (aa) {
|
||||
#define __ALPHAS__(B) \
|
||||
A(0.00), A(0.00), A(0.00), A(0.00), A(0.33), A(0.71), A(0.93), A(1.00), A(0.93), A(0.71), A(0.33), A(0.00), A(0.00), A(0.00), A(0.00), \
|
||||
A(0.00), A(0.00), A(0.00), A(0.75), A(0.68), B(0.29), B(0.07), B(0.00), B(0.07), B(0.29), A(0.68), A(0.75), A(0.00), A(0.00), A(0.00), \
|
||||
A(0.00), A(0.00), A(0.90), B(0.26), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.34), A(0.90), A(0.00), A(0.00), \
|
||||
A(0.00), A(0.75), B(0.34), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.26), A(0.75), A(0.00), \
|
||||
A(0.33), A(0.68), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(0.68), A(0.33), \
|
||||
A(0.71), B(0.29), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.29), A(0.71), \
|
||||
A(0.93), B(0.07), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.07), A(0.93), \
|
||||
A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \
|
||||
A(0.93), B(0.07), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.07), A(0.93), \
|
||||
A(0.71), B(0.29), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.29), A(0.71), \
|
||||
A(0.33), A(0.68), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(0.68), A(0.33), \
|
||||
A(0.00), A(0.75), B(0.34), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.26), A(0.75), A(0.00), \
|
||||
A(0.00), A(0.00), A(0.90), B(0.26), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.34), A(0.90), A(0.00), A(0.00), \
|
||||
A(0.00), A(0.00), A(0.00), A(0.75), A(0.68), B(0.29), B(0.07), B(0.00), B(0.07), B(0.29), A(0.68), A(0.75), A(0.00), A(0.00), A(0.00), \
|
||||
A(0.00), A(0.00), A(0.00), A(0.00), A(0.33), A(0.71), A(0.93), A(1.00), A(0.93), A(0.71), A(0.33), A(0.00), A(0.00), A(0.00), A(0.00),
|
||||
|
||||
DEF_ALPHAS(15)
|
||||
#undef __ALPHAS__
|
||||
LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 15, 15, alpha, mode);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template <class COMBFUNC> class _LICE_CircleDrawer
|
||||
{
|
||||
public:
|
||||
|
||||
static void DrawClippedPt(LICE_IBitmap* dest, int x, int y, const int *clip,
|
||||
int r, int g, int b, int a, int alpha, bool doclip)
|
||||
{
|
||||
if (doclip && (x < clip[0] || x >= clip[2] || y < clip[1] || y >= clip[3])) return;
|
||||
LICE_pixel* px = dest->getBits()+y*dest->getRowSpan()+x;
|
||||
COMBFUNC::doPix((LICE_pixel_chan*)px, r, g, b, a, alpha);
|
||||
}
|
||||
|
||||
static void DrawClippedHorzLine(LICE_IBitmap* dest, int y, int xlo, int xhi, const int *clip,
|
||||
int r, int g, int b, int a, int alpha, bool doclip)
|
||||
{
|
||||
if (doclip)
|
||||
{
|
||||
if (y < clip[1] || y >= clip[3]) return;
|
||||
xlo = lice_max(xlo, clip[0]);
|
||||
xhi = lice_min(xhi, clip[2]-1);
|
||||
}
|
||||
LICE_pixel* px = dest->getBits()+y*dest->getRowSpan()+xlo;
|
||||
while (xlo <= xhi)
|
||||
{
|
||||
COMBFUNC::doPix((LICE_pixel_chan*)px, r, g, b, a, alpha);
|
||||
++px;
|
||||
++xlo;
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawClippedVertLine(LICE_IBitmap* dest, int x, int ylo, int yhi, const int *clip,
|
||||
int r, int g, int b, int a, int alpha, bool doclip)
|
||||
{
|
||||
if (doclip)
|
||||
{
|
||||
if (x < clip[0] || x >= clip[2]) return;
|
||||
ylo = lice_max(ylo, clip[1]);
|
||||
yhi = lice_min(yhi, clip[3]-1);
|
||||
}
|
||||
int span=dest->getRowSpan();
|
||||
LICE_pixel* px = dest->getBits()+ylo*span+x;
|
||||
while (ylo <= yhi)
|
||||
{
|
||||
COMBFUNC::doPix((LICE_pixel_chan*)px, r, g, b, a, alpha);
|
||||
px += span;
|
||||
++ylo;
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawClippedCircleAA(LICE_IBitmap* dest, float cx, float cy, float rad,
|
||||
const int *clip, LICE_pixel color, int ai, bool filled, bool doclip)
|
||||
{
|
||||
int r = LICE_GETR(color), g = LICE_GETG(color), b = LICE_GETB(color), a = LICE_GETA(color);
|
||||
|
||||
const int cx0=(int)floor(cx+0.5f);
|
||||
const int cy0=(int)floor(cy+0.5f);
|
||||
|
||||
int y=(int)rad;
|
||||
double w=rad-floor(rad);
|
||||
int wa=(int)((double)ai*w);
|
||||
|
||||
DrawClippedPt(dest, cx0, cy0-y-1, clip, r, g, b, a, wa, doclip);
|
||||
DrawClippedPt(dest, cx0, cy0+y+1, clip, r, g, b, a, wa, doclip);
|
||||
DrawClippedPt(dest, cx0-y-1, cy0, clip, r, g, b, a, wa, doclip);
|
||||
DrawClippedPt(dest, cx0+y+1, cy0, clip, r, g, b, a, wa, doclip);
|
||||
|
||||
if (filled)
|
||||
{
|
||||
DrawClippedVertLine(dest, cx0, cy0-y, cy0-1, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedVertLine(dest, cx0, cy0+1, cy0+y, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedHorzLine(dest, cy0, cx0-y, cx0+y, clip, r, g, b, a, ai, doclip);
|
||||
}
|
||||
else
|
||||
{
|
||||
int iwa=ai-wa;
|
||||
DrawClippedPt(dest, cx0, cy0-y, clip, r, g, b, a, iwa, doclip);
|
||||
DrawClippedPt(dest, cx0+y, cy0, clip, r, g, b, a, iwa, doclip);
|
||||
DrawClippedPt(dest, cx0, cy0+y, clip, r, g, b, a, iwa, doclip);
|
||||
DrawClippedPt(dest, cx0-y, cy0, clip, r, g, b, a, iwa, doclip);
|
||||
}
|
||||
|
||||
double r2=rad*rad;
|
||||
double yf=sqrt(r2-1.0);
|
||||
int yl=(int)(yf+0.5);
|
||||
|
||||
int x=1;
|
||||
while (x <= yl)
|
||||
{
|
||||
y=(int)yf;
|
||||
w=yf-floor(yf);
|
||||
wa=(int)((double)ai*w);
|
||||
|
||||
DrawClippedPt(dest, cx0-x, cy0-y-1, clip, r, g, b, a, wa, doclip);
|
||||
DrawClippedPt(dest, cx0-x, cy0+y+1, clip, r, g, b, a, wa, doclip);
|
||||
DrawClippedPt(dest, cx0+x, cy0-y-1, clip, r, g, b, a, wa, doclip);
|
||||
DrawClippedPt(dest, cx0+x, cy0+y+1, clip, r, g, b, a, wa, doclip);
|
||||
if (x != yl)
|
||||
{
|
||||
DrawClippedPt(dest, cx0-y-1, cy0-x, clip, r, g, b, a, wa, doclip);
|
||||
DrawClippedPt(dest, cx0+y+1, cy0-x, clip, r, g, b, a, wa, doclip);
|
||||
DrawClippedPt(dest, cx0-y-1, cy0+x, clip, r, g, b, a, wa, doclip);
|
||||
DrawClippedPt(dest, cx0+y+1, cy0+x, clip, r, g, b, a, wa, doclip);
|
||||
}
|
||||
|
||||
if (filled)
|
||||
{
|
||||
DrawClippedVertLine(dest, cx0-x, cy0-y, cy0-x-1, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedVertLine(dest, cx0-x, cy0+x+1, cy0+y, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedHorzLine(dest, cy0-x, cx0-y, cx0-x, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedHorzLine(dest, cy0-x, cx0+x, cx0+y, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedHorzLine(dest, cy0+x, cx0-y, cx0-x, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedHorzLine(dest, cy0+x, cx0+x, cx0+y, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedVertLine(dest, cx0+x, cy0-y, cy0-x-1, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedVertLine(dest, cx0+x, cy0+x+1, cy0+y, clip, r, g, b, a, ai, doclip);
|
||||
}
|
||||
else
|
||||
{
|
||||
int iwa=ai-wa;
|
||||
DrawClippedPt(dest, cx0-y, cy0-x, clip, r, g, b, a, iwa, doclip);
|
||||
DrawClippedPt(dest, cx0+y, cy0-x, clip, r, g, b, a, iwa, doclip);
|
||||
DrawClippedPt(dest, cx0-x, cy0+y, clip, r, g, b, a, iwa, doclip);
|
||||
DrawClippedPt(dest, cx0+x, cy0+y, clip, r, g, b, a, iwa, doclip);
|
||||
if (x != yl)
|
||||
{
|
||||
DrawClippedPt(dest, cx0-x, cy0-y, clip, r, g, b, a, iwa, doclip);
|
||||
DrawClippedPt(dest, cx0+x, cy0-y, clip, r, g, b, a, iwa, doclip);
|
||||
DrawClippedPt(dest, cx0-y, cy0+x, clip, r, g, b, a, iwa, doclip);
|
||||
DrawClippedPt(dest, cx0+y, cy0+x, clip, r, g, b, a, iwa, doclip);
|
||||
}
|
||||
}
|
||||
|
||||
++x;
|
||||
yf=sqrt(r2-(double)(x*x));
|
||||
yl=(int)(yf+0.5);
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawClippedCircle(LICE_IBitmap* dest, float cx, float cy, float rad,
|
||||
const int *clip, LICE_pixel color, int ai, bool filled, bool doclip)
|
||||
{
|
||||
const int r = LICE_GETR(color), g = LICE_GETG(color), b = LICE_GETB(color), a = LICE_GETA(color);
|
||||
|
||||
const int cx0=(int)floor(cx+0.5f);
|
||||
const int cy0=(int)floor(cy+0.5f);
|
||||
const int r0=(int)(rad+0.5f);
|
||||
|
||||
if (filled)
|
||||
{
|
||||
DrawClippedVertLine(dest, cx0, cy0-r0, cy0-1, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedVertLine(dest, cx0, cy0+1, cy0+r0, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedHorzLine(dest, cy0, cx0-r0, cx0+r0, clip, r, g, b, a, ai, doclip);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawClippedPt(dest, cx0, cy0-r0, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedPt(dest, cx0+r0, cy0, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedPt(dest, cx0, cy0+r0, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedPt(dest, cx0-r0, cy0, clip, r, g, b, a, ai, doclip);
|
||||
}
|
||||
|
||||
int x=0;
|
||||
int y=r0;
|
||||
int e=-r0;
|
||||
while (++x < y)
|
||||
{
|
||||
if (e < 0)
|
||||
{
|
||||
e += 2*x+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
--y;
|
||||
e += 2*(x-y)+1;
|
||||
}
|
||||
|
||||
if (filled)
|
||||
{
|
||||
DrawClippedVertLine(dest, cx0-x, cy0-y, cy0-x-1, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedVertLine(dest, cx0-x, cy0+x+1, cy0+y, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedHorzLine(dest, cy0-x, cx0-y, cx0-x, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedHorzLine(dest, cy0-x, cx0+x, cx0+y, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedHorzLine(dest, cy0+x, cx0-y, cx0-x, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedHorzLine(dest, cy0+x, cx0+x, cx0+y, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedVertLine(dest, cx0+x, cy0-y, cy0-x-1, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedVertLine(dest, cx0+ x, cy0+x+1, cy0+y, clip, r, g, b, a, ai, doclip);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawClippedPt(dest, cx0-x, cy0-y, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedPt(dest, cx0-x, cy0+y, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedPt(dest, cx0+x, cy0-y, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedPt(dest, cx0+x, cy0+y, clip, r, g, b, a, ai, doclip);
|
||||
if (x != y)
|
||||
{
|
||||
DrawClippedPt(dest, cx0-y, cy0-x, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedPt(dest, cx0-y, cy0+x, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedPt(dest, cx0+y, cy0-x, clip, r, g, b, a, ai, doclip);
|
||||
DrawClippedPt(dest, cx0+y, cy0+x, clip, r, g, b, a, ai, doclip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
static void __DrawCircleClipped(LICE_IBitmap* dest, float cx, float cy, float rad,
|
||||
LICE_pixel color, int ia, bool aa, bool filled, int mode, const int *clip, bool doclip)
|
||||
{
|
||||
// todo: more clipped/filled versions (to optimize constants out?)
|
||||
if (aa)
|
||||
{
|
||||
#define __LICE__ACTION(COMBFUNC) _LICE_CircleDrawer<COMBFUNC>::DrawClippedCircleAA(dest, cx, cy, rad, clip, color, ia, filled, doclip)
|
||||
__LICE_ACTION_NOSRCALPHA(mode, ia,false)
|
||||
#undef __LICE__ACTION
|
||||
}
|
||||
else
|
||||
{
|
||||
#define __LICE__ACTION(COMBFUNC) _LICE_CircleDrawer<COMBFUNC>::DrawClippedCircle(dest, cx, cy, rad, clip, color, ia, filled, doclip)
|
||||
__LICE_ACTION_CONSTANTALPHA(mode,ia,false)
|
||||
#undef __LICE__ACTION
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void __DrawArc(int w, int h, LICE_IBitmap* dest, float cx, float cy, float rad, double anglo, double anghi,
|
||||
LICE_pixel color, int ialpha, bool aa, int mode)
|
||||
{
|
||||
const int __sc = (int)dest->Extended(LICE_EXT_GET_SCALING,NULL);
|
||||
if (__sc>0)
|
||||
{
|
||||
__LICE_SCU(w);
|
||||
__LICE_SCU(h);
|
||||
if (!IGNORE_SCALING(mode))
|
||||
{
|
||||
__LICE_SC(cx);
|
||||
__LICE_SC(cy);
|
||||
__LICE_SC(rad);
|
||||
}
|
||||
}
|
||||
// -2PI <= anglo <= anghi <= 2PI
|
||||
anglo += 2.0*_PI;
|
||||
anghi += 2.0*_PI;
|
||||
|
||||
// 0 <= anglo <= anghi <= 4PI
|
||||
|
||||
double next_ang = anglo - fmod(anglo,0.5*_PI);
|
||||
|
||||
int ly = (int)floor(cy - rad*cos(anglo) + 0.5);
|
||||
int lx = (int)floor(cx + rad*sin(anglo) + 0.5);
|
||||
|
||||
while (anglo < anghi)
|
||||
{
|
||||
next_ang += 0.5*_PI;
|
||||
if (next_ang > anghi) next_ang = anghi;
|
||||
|
||||
int yhi = (int) floor(cy-rad*cos(next_ang)+0.5);
|
||||
int xhi = (int) floor(cx+rad*sin(next_ang)+0.5);
|
||||
int ylo = ly;
|
||||
int xlo = lx;
|
||||
|
||||
ly = yhi;
|
||||
lx = xhi;
|
||||
|
||||
if (yhi < ylo) { int tmp = ylo; ylo = yhi; yhi=tmp; }
|
||||
if (xhi < xlo) { int tmp = xlo; xlo = xhi; xhi=tmp; }
|
||||
|
||||
anglo = next_ang;
|
||||
|
||||
if (xhi != cx) xhi++;
|
||||
if (yhi != cy) yhi++;
|
||||
|
||||
const int clip[4]={lice_max(xlo,0),lice_max(0, ylo),lice_min(w,xhi+1),lice_min(h, yhi+1)};
|
||||
|
||||
__DrawCircleClipped(dest,cx,cy,rad,color,ialpha,aa,false,mode,clip,true);
|
||||
}
|
||||
}
|
||||
|
||||
void LICE_Arc(LICE_IBitmap* dest, float cx, float cy, float r, float minAngle, float maxAngle,
|
||||
LICE_pixel color, float alpha, int mode, bool aa)
|
||||
{
|
||||
if (!dest) return;
|
||||
|
||||
if (dest->isFlipped()) { cy=dest->getHeight()-1-cy; minAngle=_PI-minAngle; maxAngle=_PI-maxAngle; }
|
||||
|
||||
if (maxAngle < minAngle)
|
||||
{
|
||||
float tmp=maxAngle;
|
||||
maxAngle=minAngle;
|
||||
minAngle=tmp;
|
||||
}
|
||||
|
||||
if (maxAngle - minAngle >= 2.0f*_PI)
|
||||
{
|
||||
LICE_Circle(dest,cx,cy,r,color,alpha,mode,aa);
|
||||
return;
|
||||
}
|
||||
|
||||
if (maxAngle >= 2.0f*_PI)
|
||||
{
|
||||
float tmp = fmod(maxAngle,2.0f*_PI);
|
||||
minAngle -= maxAngle - tmp; // reduce by factors of 2PI
|
||||
maxAngle = tmp;
|
||||
}
|
||||
else if (minAngle <= -2.0f*_PI)
|
||||
{
|
||||
float tmp = fmod(minAngle,2.0f*_PI);
|
||||
maxAngle -= minAngle - tmp; // toward zero by factors of 2pi
|
||||
minAngle = tmp;
|
||||
}
|
||||
|
||||
// -2PI <= minAngle <= maxAngle <= 2PI
|
||||
|
||||
int ia = (int) (alpha*256.0f);
|
||||
if (!ia) return;
|
||||
|
||||
__DrawArc(dest->getWidth(),dest->getHeight(),dest,cx,cy,r,minAngle,maxAngle,color,ia,aa,mode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void LICE_Circle(LICE_IBitmap* dest, float cx, float cy, float r, LICE_pixel color, float alpha, int mode, bool aa)
|
||||
{
|
||||
if (!dest) return;
|
||||
|
||||
int w = dest->getWidth(), h = dest->getHeight();
|
||||
const int __sc = (int)dest->Extended(LICE_EXT_GET_SCALING,NULL);
|
||||
if (__sc>0)
|
||||
{
|
||||
__LICE_SCU(w);
|
||||
__LICE_SCU(h);
|
||||
if (!IGNORE_SCALING(mode))
|
||||
{
|
||||
__LICE_SC(cx);
|
||||
__LICE_SC(cy);
|
||||
__LICE_SC(r);
|
||||
}
|
||||
}
|
||||
|
||||
const int clip[4] = { 0, 0, w, h };
|
||||
if (w < 1 || h <1 || r<0 ||
|
||||
(int)cx+(int)r < -2 || (int)cy + (int)r < - 2 ||
|
||||
(int)cx-(int)r > w + 2 || (int)cy - (int)r > h + 2
|
||||
) return;
|
||||
|
||||
int ia = (int) (alpha*256.0f);
|
||||
if (!ia) return;
|
||||
|
||||
if (CachedCircle(dest, cx, cy, r, color, alpha, mode|LICE_BLIT_IGNORE_SCALING, aa, false)) return;
|
||||
|
||||
if (dest->isFlipped()) cy=h-1-cy;
|
||||
|
||||
const bool doclip = !(cx-r-2 >= 0 && cy-r-2 >= 0 && cx+r+2 < w && cy+r+2 < h);
|
||||
|
||||
__DrawCircleClipped(dest,cx,cy,r,color,ia,aa,false,mode,clip,doclip);
|
||||
}
|
||||
|
||||
void LICE_FillCircle(LICE_IBitmap* dest, float cx, float cy, float r, LICE_pixel color, float alpha, int mode, bool aa)
|
||||
{
|
||||
if (!dest) return;
|
||||
|
||||
int w = dest->getWidth(), h = dest->getHeight();
|
||||
const int __sc = (int)dest->Extended(LICE_EXT_GET_SCALING,NULL);
|
||||
if (__sc>0)
|
||||
{
|
||||
__LICE_SCU(w);
|
||||
__LICE_SCU(h);
|
||||
if (!IGNORE_SCALING(mode))
|
||||
{
|
||||
__LICE_SC(cx);
|
||||
__LICE_SC(cy);
|
||||
__LICE_SC(r);
|
||||
}
|
||||
}
|
||||
|
||||
if (w < 1 || h < 1 || r < 0.0 ||
|
||||
(int)cx+(int)r < -2 || (int)cy + (int)r < - 2 ||
|
||||
(int)cx-(int)r > w + 2 || (int)cy - (int)r > h + 2
|
||||
) return;
|
||||
|
||||
const int ia = (int) (alpha*256.0f);
|
||||
if (!ia) return;
|
||||
|
||||
if (CachedCircle(dest, cx, cy, r, color, alpha, mode|LICE_BLIT_IGNORE_SCALING, aa, true)) return;
|
||||
|
||||
if (dest->isFlipped()) cy=h-1-cy;
|
||||
|
||||
const int clip[4] = { 0, 0, w, h };
|
||||
|
||||
const bool doclip = !(cx-r-2 >= 0 && cy-r-2 >= 0 && cx+r+2 < w && cy+r+2 < h);
|
||||
__DrawCircleClipped(dest,cx,cy,r,color,ia,aa,true,mode,clip,doclip);
|
||||
}
|
||||
|
||||
|
||||
void LICE_RoundRect(LICE_IBitmap *drawbm, float xpos, float ypos, float w, float h, int cornerradius,
|
||||
LICE_pixel col, float alpha, int mode, bool aa)
|
||||
{
|
||||
xpos = floor(xpos+0.5);
|
||||
ypos = floor(ypos+0.5);
|
||||
w = floor(w+0.5);
|
||||
h = floor(h+0.5);
|
||||
if (cornerradius>0)
|
||||
{
|
||||
float cr=cornerradius;
|
||||
if (cr > w*0.5) cr=w*0.5;
|
||||
if (cr > h*0.5) cr=h*0.5;
|
||||
cr=floor(cr);
|
||||
|
||||
if (cr>=2)
|
||||
{
|
||||
double adj = 0.0;
|
||||
const int __sc = IGNORE_SCALING(mode) ? 0 : drawbm ? (int)drawbm->Extended(LICE_EXT_GET_SCALING,NULL) : 0;
|
||||
if (__sc>0)
|
||||
{
|
||||
adj = 1.0 - 256.0/__sc;
|
||||
|
||||
LICE_FLine(drawbm,xpos+cr+adj,ypos+adj,xpos+w-cr,ypos+adj,col,alpha,mode,true);
|
||||
LICE_FLine(drawbm,xpos+cr-1+adj,ypos+h-adj,xpos+w-cr-adj,ypos+h-adj,col,alpha,mode,true);
|
||||
LICE_FLine(drawbm,xpos+w-adj,ypos+cr+adj,xpos+w-adj,ypos+h-cr-adj,col,alpha,mode,true);
|
||||
LICE_FLine(drawbm,xpos+adj,ypos+cr-1+adj,xpos+adj,ypos+h-cr-adj,col,alpha,mode,true);
|
||||
// aa=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LICE_Line(drawbm,xpos+cr,ypos,xpos+w-cr,ypos,col,alpha,mode,aa);
|
||||
LICE_Line(drawbm,xpos+cr-1,ypos+h,xpos+w-cr,ypos+h,col,alpha,mode,aa);
|
||||
LICE_Line(drawbm,xpos+w,ypos+cr,xpos+w,ypos+h-cr,col,alpha,mode,aa);
|
||||
LICE_Line(drawbm,xpos,ypos+cr-1,xpos,ypos+h-cr,col,alpha,mode,aa);
|
||||
}
|
||||
|
||||
LICE_Arc(drawbm,xpos+cr+adj,ypos+cr+adj,cr,-_PI*0.5f,0,col,alpha,mode,aa);
|
||||
LICE_Arc(drawbm,xpos+w-cr-adj,ypos+cr+adj,cr,0,_PI*0.5f,col,alpha,mode,aa);
|
||||
LICE_Arc(drawbm,xpos+w-cr-adj,ypos+h-cr-adj,cr,_PI*0.5f,_PI,col,alpha,mode,aa);
|
||||
LICE_Arc(drawbm,xpos+cr+adj,ypos+h-cr-adj,cr,_PI,_PI*1.5f,col,alpha,mode,aa);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LICE_DrawRect(drawbm, (int)xpos, (int)ypos, (int)w, (int)h, col, alpha, mode);
|
||||
}
|
||||
|
||||
306
oversampling/WDL/lice/lice_bezier.h
Normal file
306
oversampling/WDL/lice/lice_bezier.h
Normal file
@@ -0,0 +1,306 @@
|
||||
#ifndef _LICE_BEZIER_
|
||||
#define _LICE_BEZIER_
|
||||
|
||||
#include "lice.h"
|
||||
#include <math.h>
|
||||
|
||||
// Returns quadratic bezier x, y for a given t in [0,1].
|
||||
template <class T>
|
||||
void LICE_Bezier(T ctrl_x1, T ctrl_x2, T ctrl_x3,
|
||||
T ctrl_y1, T ctrl_y2, T ctrl_y3, double t, T* pX, T* pY)
|
||||
{
|
||||
double it = 1.0 - t;
|
||||
double a = it * it;
|
||||
double b = 2.0 * it * t;
|
||||
double c = t * t;
|
||||
*pX = (T) (a * (double) ctrl_x1 + b * (double) ctrl_x2 + c * (double) ctrl_x3);
|
||||
*pY = (T) (a * (double) ctrl_y1 + b * (double) ctrl_y2 + c * (double) ctrl_y3);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void LICE_CBezier_GetCoeffs(T ctrl_x1, T ctrl_x2, T ctrl_x3, T ctrl_x4,
|
||||
T ctrl_y1, T ctrl_y2, T ctrl_y3, T ctrl_y4,
|
||||
double* pAX, double* pBX, double* pCX,
|
||||
double* pAY, double* pBY, double* pCY)
|
||||
{
|
||||
double cx = *pCX = 3.0 * (double) (ctrl_x2 - ctrl_x1);
|
||||
double bx = *pBX = 3.0 * (double) (ctrl_x3 - ctrl_x2) - cx;
|
||||
*pAX = (double) (ctrl_x4 - ctrl_x1) - cx - bx;
|
||||
double cy = *pCY = 3.0 * (double) (ctrl_y2 - ctrl_y1);
|
||||
double by = *pBY = 3.0 * (double) (ctrl_y3 - ctrl_y2) - cy;
|
||||
*pAY = (double) (ctrl_y4 - ctrl_y1) - cy - by;
|
||||
}
|
||||
|
||||
// Returns cubic bezier x, y for a given t in [0,1].
|
||||
template <class T>
|
||||
void LICE_CBezier(T ctrl_x1, T ctrl_x2, T ctrl_x3, T ctrl_x4,
|
||||
T ctrl_y1, T ctrl_y2, T ctrl_y3, T ctrl_y4, double t, T* pX, T* pY)
|
||||
{
|
||||
double ax, bx, cx, ay, by, cy;
|
||||
LICE_CBezier_GetCoeffs(ctrl_x1, ctrl_x2, ctrl_x3, ctrl_x4,
|
||||
ctrl_y1, ctrl_y2, ctrl_y3, ctrl_y4,
|
||||
&ax, &bx, &cx, &ay, &by, &cy);
|
||||
|
||||
double t2 = t * t;
|
||||
double t3 = t * t2;
|
||||
*pX = (T) (ax * t3 + bx * t2 + cx * t) + ctrl_x1;
|
||||
*pY = (T) (ay * t3 + by * t2 + cy * t) + ctrl_y1;
|
||||
}
|
||||
|
||||
// Returns quadratic bezier y for a given x in [x1, x3] (for rasterizing).
|
||||
// ctrl_x1 < ctrl_x3 required.
|
||||
template <class T>
|
||||
T LICE_Bezier_GetY(T ctrl_x1, T ctrl_x2, T ctrl_x3, T ctrl_y1, T ctrl_y2, T ctrl_y3, T x, double* pt=0)
|
||||
{
|
||||
if (x <= ctrl_x1)
|
||||
{
|
||||
if (pt) *pt = 0.0;
|
||||
return ctrl_y1;
|
||||
}
|
||||
if (x >= ctrl_x3)
|
||||
{
|
||||
if (pt) *pt = 1.0;
|
||||
return ctrl_y3;
|
||||
}
|
||||
|
||||
double t, a = (double) ctrl_x1 - (double) (2 * ctrl_x2) + (double) ctrl_x3;
|
||||
if (a == 0.0)
|
||||
{
|
||||
t=(ctrl_x1 == ctrl_x3) ? 0.0 : (x-ctrl_x1)/(ctrl_x3-ctrl_x1);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = (double) (ctrl_x2 - ctrl_x1);
|
||||
t = (-t + sqrt(t * t - a * (ctrl_x1 - x))) / a;
|
||||
}
|
||||
const double it = 1.0 - t;
|
||||
|
||||
if (pt) *pt = t;
|
||||
return (T) (it * it * (double) ctrl_y1 + t * (2.0*it*(double)ctrl_y2 + t * (double) ctrl_y3));
|
||||
}
|
||||
|
||||
// Special case for x = y = [0,1]
|
||||
template <class T>
|
||||
void LICE_Bezier_Norm(T ctrl_x2, T ctrl_y2, double t, T* pX, T* pY)
|
||||
{
|
||||
double b = 2.0 * (1.0 - t) * t;
|
||||
double c = t * t;
|
||||
*pX = (T) (b * (double) ctrl_x2 + c);
|
||||
*pY = (T) (b * (double) ctrl_y2 + c);
|
||||
}
|
||||
|
||||
// special case for x = y = [0,1].
|
||||
template <class T>
|
||||
T LICE_Bezier_GetY_Norm(T ctrl_x2, T ctrl_y2, T x)
|
||||
{
|
||||
if (x < (T) 0.0) {
|
||||
return (T) 0.0;
|
||||
}
|
||||
if (x >= (T) 1.0) {
|
||||
return (T) 1.0;
|
||||
}
|
||||
if (ctrl_x2 == (T) 0.5) { // linear
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// this causes ICC 11.0 to produce bad results on OSX/386
|
||||
double b = (double) (2 * ctrl_x2);
|
||||
double a = 1.0 - b;
|
||||
double c = (double) -x;
|
||||
double t = (-b + sqrt(b * b - 4.0 * a * c)) / (2.0 * a);
|
||||
|
||||
b = 2.0 * (1.0 - t) * t;
|
||||
c = t * t;
|
||||
return (T) (b * (double) ctrl_y2 + c);
|
||||
|
||||
// the simplified math below works properly
|
||||
*/
|
||||
|
||||
|
||||
const double t = (-ctrl_x2 + sqrt(ctrl_x2 * (ctrl_x2 - 2.0*x) + x)) / (1.0-2.0*ctrl_x2);
|
||||
|
||||
return (T) (((2.0 * (1.0-t)) * ctrl_y2 + t)*t);
|
||||
}
|
||||
|
||||
// Finds the cardinal bezier control points surrounding x2.
|
||||
// Cubic bezier over (x1,x1b,x2a,x2), (y1,y1b,y2a,y2) or
|
||||
// quadratic bezier over (x1,x1b,mid(x1b,x2a)), (y1,y1b,mid(y1b,y2a))
|
||||
// will smoothly interpolate between (x1,y1) and (x2,y2) while preserving all existing values.
|
||||
// The lower alpha is, the more tame the bezier curve will be (0.25 = subtle).
|
||||
template <class T>
|
||||
void LICE_Bezier_FindCardinalCtlPts(double alpha, T x1, T x2, T x3, T y1, T y2, T y3,
|
||||
T* ctrl_x2a, T* ctrl_x2b, T* ctrl_y2a, T* ctrl_y2b)
|
||||
{
|
||||
double dxa = alpha * (double) (x2 - x1);
|
||||
double dxb = alpha * (double) (x3 - x2);
|
||||
if (ctrl_x2a) *ctrl_x2a = x2 - (T) dxa;
|
||||
if (ctrl_x2b) *ctrl_x2b = x2 + (T) dxb;
|
||||
|
||||
if (x1 == x3)
|
||||
{
|
||||
if (ctrl_y2a) *ctrl_y2a = y2;
|
||||
if (ctrl_y2b) *ctrl_y2b = y2;
|
||||
}
|
||||
else
|
||||
{
|
||||
double m = (double) (y3 - y1) / (double) (x3 - x1);
|
||||
if (ctrl_y2a) *ctrl_y2a = y2 - (T) (m * dxa);
|
||||
if (ctrl_y2b) *ctrl_y2b = y2 + (T) (m * dxb);
|
||||
}
|
||||
}
|
||||
|
||||
// Basic quadratic nurbs. Given a set of n (x,y) pairs,
|
||||
// populate pDest with the unit-spaced nurbs curve.
|
||||
// pDest must be passed in with size (int) (*(pX+n-1) - *pX).
|
||||
// pX must be monotonically increasing and no duplicates.
|
||||
template <class T>
|
||||
inline void LICE_QNurbs(T* pDest, int pDest_sz, int *pX, T* pY, int n, bool hit_each_point=false)
|
||||
{
|
||||
int x1 = *pX++, x2 = *pX++;
|
||||
T y1 = *pY++, y2 = *pY++;
|
||||
double xm1, xm2 = 0.5 * (x1 + x2);
|
||||
double ym1, ym2 = 0.5 * (y1 + y2);
|
||||
|
||||
double yi = y1, m = (y2 - y1) / (double) (x2 - x1);
|
||||
int xi = x1, iend = (int)floor(xm2+0.5); // this (and below) was previously ceil(), but can't see any reason why it should matter (this should be more correct, I'd imagine)
|
||||
for (; xi < iend; xi++, yi += m)
|
||||
{
|
||||
if (--pDest_sz<0) return;
|
||||
*pDest++ = (T) yi;
|
||||
}
|
||||
|
||||
for (int i = 2; i < n; ++i)
|
||||
{
|
||||
x1 = x2;
|
||||
x2 = *pX++;
|
||||
y1 = y2;
|
||||
y2 = *pY++;
|
||||
|
||||
xm1 = xm2;
|
||||
xm2 = 0.5 * (x1 + x2);
|
||||
ym1 = ym2;
|
||||
ym2 = 0.5 * (y1 + y2);
|
||||
|
||||
iend = (int)floor(xm2+0.5);
|
||||
if (ym1 == ym2 && y1 == ym1)
|
||||
{
|
||||
for (; xi < iend; xi++)
|
||||
{
|
||||
if (--pDest_sz<0) return;
|
||||
*pDest++ = (T) y1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
double y1u = y1;
|
||||
if (hit_each_point)
|
||||
{
|
||||
// y1 = LICE_Bezier_GetY(0,0.5,1.0, ym1,y1u,ym2,0.5), this is the inverse
|
||||
y1u = 2.0 * y1 - 0.5 * (ym1 + ym2);
|
||||
}
|
||||
for (; xi < iend; xi++)
|
||||
{
|
||||
if (--pDest_sz<0) return;
|
||||
*pDest++ = (T) LICE_Bezier_GetY(xm1, (double)x1, xm2, ym1, (double)y1u, ym2, (double)xi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = (y2 - y1) / (double) (x2 - x1);
|
||||
yi = ym2;
|
||||
for (; xi < x2; xi++, yi += m)
|
||||
{
|
||||
if (--pDest_sz<0) return;
|
||||
*pDest++ = (T) yi;
|
||||
}
|
||||
}
|
||||
|
||||
#define CBEZ_ITERS 8
|
||||
|
||||
#define EVAL_CBEZ(tx,a,b,c,d,t) \
|
||||
{ \
|
||||
double _t2=t*t; \
|
||||
tx=(a*t*_t2+b*_t2+c*t+d); \
|
||||
}
|
||||
|
||||
#define EVAL_CBEZXY(tx, ty, ax, bx, cx, dx, ay, by, cy, dy, t) \
|
||||
{ \
|
||||
double _t2=t*t; \
|
||||
double _t3=t*_t2; \
|
||||
tx=ax*_t3+bx*_t2+cx*t+dx; \
|
||||
ty=ay*_t3+by*_t2+cy*t+dy; \
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T LICE_CBezier_GetY(T ctrl_x1, T ctrl_x2, T ctrl_x3, T ctrl_x4,
|
||||
T ctrl_y1, T ctrl_y2, T ctrl_y3, T ctrl_y4, T x,
|
||||
T* pNextX = 0, T* pdYdX = 0, double* ptLo = 0, double* ptHi = 0)
|
||||
{
|
||||
if (x < ctrl_x1)
|
||||
{
|
||||
if (pNextX) *pNextX = ctrl_x1;
|
||||
if (pdYdX) *pdYdX = (T) 0.0;
|
||||
return ctrl_y1;
|
||||
}
|
||||
if (x >= ctrl_x4)
|
||||
{
|
||||
if (pNextX) *pNextX = ctrl_x4;
|
||||
if (pdYdX) *pdYdX = (T) 0.0;
|
||||
return ctrl_y4;
|
||||
}
|
||||
|
||||
double ax, bx, cx, ay, by, cy;
|
||||
LICE_CBezier_GetCoeffs(ctrl_x1, ctrl_x2, ctrl_x3, ctrl_x4,
|
||||
ctrl_y1, ctrl_y2, ctrl_y3, ctrl_y4,
|
||||
&ax, &bx, &cx, &ay, &by, &cy);
|
||||
|
||||
double tx, t, tLo = 0.0, tHi = 1.0;
|
||||
double xLo=0.0, xHi=0.0, yLo, yHi;
|
||||
int i;
|
||||
for (i = 0; i < CBEZ_ITERS; ++i)
|
||||
{
|
||||
t = 0.5 * (tLo + tHi);
|
||||
EVAL_CBEZ(tx, ax, bx, cx, (double) ctrl_x1, t);
|
||||
if (tx < (double) x)
|
||||
{
|
||||
tLo = t;
|
||||
xLo = tx;
|
||||
}
|
||||
else if (tx > (double) x)
|
||||
{
|
||||
tHi = t;
|
||||
xHi = tx;
|
||||
}
|
||||
else
|
||||
{
|
||||
tLo = t;
|
||||
xLo = tx;
|
||||
tHi = t + 1.0/pow(2.0,CBEZ_ITERS);
|
||||
if (tHi > 1.0) tHi = 1.0; // floating point error
|
||||
EVAL_CBEZ(xHi, ax, bx, cx, (double) ctrl_x1, tHi);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tLo == 0.0) EVAL_CBEZ(xLo, ax, bx, cx, (double) ctrl_x1, 0.0);
|
||||
if (tHi == 1.0) EVAL_CBEZ(xHi, ax, bx, cx, (double) ctrl_x1, 1.0);
|
||||
|
||||
EVAL_CBEZ(yLo, ay, by, cy, (double) ctrl_y1, tLo);
|
||||
EVAL_CBEZ(yHi, ay, by, cy, (double) ctrl_y1, tHi);
|
||||
|
||||
double dYdX = (xLo == xHi ? 0.0 : (yHi - yLo) / (xHi - xLo));
|
||||
double y = yLo + ((double) x - xLo) * dYdX;
|
||||
|
||||
if (pNextX) *pNextX = (T) xHi;
|
||||
if (pdYdX) *pdYdX = (T) dYdX;
|
||||
|
||||
if (ptLo) *ptLo = tLo;
|
||||
if (ptHi) *ptHi = tHi;
|
||||
|
||||
return (T) y;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
122
oversampling/WDL/lice/lice_bmp.cpp
Normal file
122
oversampling/WDL/lice/lice_bmp.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
Cockos WDL - LICE - Lightweight Image Compositing Engine
|
||||
Copyright (C) 2007 and later, Cockos Incorporated
|
||||
File: lice_bmp.cpp (BMP loading for LICE)
|
||||
See lice.h for license and other information
|
||||
*/
|
||||
|
||||
#ifndef WDL_NO_DEFINE_MINMAX
|
||||
#define WDL_NO_DEFINE_MINMAX
|
||||
#endif
|
||||
#include "lice.h"
|
||||
#include "../wdltypes.h"
|
||||
#ifndef _WIN32
|
||||
#include "../swell/swell.h"
|
||||
#endif
|
||||
|
||||
static LICE_IBitmap *hbmToBit(HBITMAP hbm, LICE_IBitmap *bmp)
|
||||
{
|
||||
BITMAP bm;
|
||||
GetObject(hbm, sizeof(BITMAP), (LPSTR)&bm);
|
||||
|
||||
LICE_SysBitmap sysbitmap(bm.bmWidth,bm.bmHeight);
|
||||
|
||||
#ifdef _WIN32
|
||||
HDC hdc=CreateCompatibleDC(NULL);
|
||||
HGDIOBJ oldBM=SelectObject(hdc,hbm);
|
||||
|
||||
BitBlt(sysbitmap.getDC(),0,0,bm.bmWidth,bm.bmHeight,hdc,0,0,SRCCOPY);
|
||||
GdiFlush();
|
||||
|
||||
if (!bmp) bmp=new WDL_NEW LICE_MemBitmap(bm.bmWidth,bm.bmHeight);
|
||||
LICE_Copy(bmp,&sysbitmap);
|
||||
|
||||
SelectObject(hdc,oldBM);
|
||||
DeleteDC(hdc);
|
||||
#else
|
||||
LICE_Clear(&sysbitmap,0);
|
||||
RECT r={0,0,bm.bmWidth,bm.bmHeight};
|
||||
DrawImageInRect(sysbitmap.getDC(),hbm,&r);
|
||||
if (!bmp) bmp=new WDL_NEW LICE_MemBitmap(bm.bmWidth,bm.bmHeight);
|
||||
LICE_Copy(bmp,&sysbitmap);
|
||||
#endif
|
||||
|
||||
if (bmp) LICE_FillRect(bmp,0,0,bmp->getWidth(),bmp->getHeight(),LICE_RGBA(0,0,0,255),1.0f,LICE_BLIT_MODE_ADD);
|
||||
|
||||
return bmp;
|
||||
}
|
||||
|
||||
|
||||
LICE_IBitmap *LICE_LoadBMP(const char *filename, LICE_IBitmap *bmp) // returns a bitmap (bmp if nonzero) on success
|
||||
{
|
||||
HBITMAP bm=NULL;
|
||||
#ifdef _WIN32
|
||||
#ifndef WDL_NO_SUPPORT_UTF8
|
||||
#ifdef WDL_SUPPORT_WIN9X
|
||||
if (GetVersion()<0x80000000)
|
||||
#endif
|
||||
{
|
||||
WCHAR wf[2048];
|
||||
if (MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,filename,-1,wf,2048))
|
||||
bm = (HBITMAP) LoadImageW(NULL,wf,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_LOADFROMFILE);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!bm) bm=(HBITMAP) LoadImage(NULL,filename,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_LOADFROMFILE);
|
||||
#else
|
||||
bm=(HBITMAP) LoadNamedImage(filename,false);
|
||||
#endif
|
||||
if (!bm) return 0;
|
||||
|
||||
LICE_IBitmap *ret=hbmToBit(bm,bmp);
|
||||
|
||||
DeleteObject(bm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
LICE_IBitmap *LICE_LoadBMPFromResource(HINSTANCE hInst, const char *resid, LICE_IBitmap *bmp) // returns a bitmap (bmp if nonzero) on success
|
||||
{
|
||||
HBITMAP bm=(HBITMAP) LoadImage(hInst,resid,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION);
|
||||
if (!bm) return 0;
|
||||
|
||||
LICE_IBitmap *ret=hbmToBit(bm,bmp);
|
||||
|
||||
DeleteObject(bm);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
class LICE_BMPLoader
|
||||
{
|
||||
public:
|
||||
_LICE_ImageLoader_rec rec;
|
||||
LICE_BMPLoader()
|
||||
{
|
||||
rec.loadfunc = loadfunc;
|
||||
rec.get_extlist = get_extlist;
|
||||
rec._next = LICE_ImageLoader_list;
|
||||
LICE_ImageLoader_list = &rec;
|
||||
}
|
||||
|
||||
static LICE_IBitmap *loadfunc(const char *filename, bool checkFileName, LICE_IBitmap *bmpbase)
|
||||
{
|
||||
if (checkFileName)
|
||||
{
|
||||
const char *p=filename;
|
||||
while (*p)p++;
|
||||
while (p>filename && *p != '\\' && *p != '/' && *p != '.') p--;
|
||||
if (stricmp(p,".bmp")) return 0;
|
||||
}
|
||||
return LICE_LoadBMP(filename,bmpbase);
|
||||
}
|
||||
static const char *get_extlist()
|
||||
{
|
||||
return "BMP files (*.BMP)\0*.BMP\0";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
LICE_BMPLoader LICE_bmpldr;
|
||||
151
oversampling/WDL/lice/lice_colorspace.cpp
Normal file
151
oversampling/WDL/lice/lice_colorspace.cpp
Normal file
@@ -0,0 +1,151 @@
|
||||
#ifndef WDL_NO_DEFINE_MINMAX
|
||||
#define WDL_NO_DEFINE_MINMAX
|
||||
#endif
|
||||
#include "lice.h"
|
||||
#include <math.h>
|
||||
|
||||
#define LICE_COMBINE_IMPLEMENT_HSV
|
||||
#include "lice_combine.h"
|
||||
|
||||
|
||||
LICE_pixel LICE_AlterColorHSV_int(LICE_pixel color, int dH, int dS, int dV) // H is rolled over [0,384), S and V are clamped [0,255)
|
||||
{
|
||||
int h, s, v;
|
||||
LICE_RGB2HSV(LICE_GETR(color), LICE_GETG(color), LICE_GETB(color), &h, &s, &v);
|
||||
|
||||
h += dH;
|
||||
s += dS;
|
||||
v += dV;
|
||||
|
||||
if (h < 0) h += 384;
|
||||
else if (h >= 384) h -= 384;
|
||||
|
||||
if (s & ~255)
|
||||
{
|
||||
if (s<0) s = 0;
|
||||
else s = 255;
|
||||
}
|
||||
|
||||
if (v&~255)
|
||||
{
|
||||
if (v < 0) v = 0.;
|
||||
else v = 255;
|
||||
}
|
||||
|
||||
return LICE_HSV2Pix(h, s, v, LICE_GETA(color));
|
||||
}
|
||||
|
||||
LICE_pixel LICE_AlterColorHSV(LICE_pixel color, float dH, float dS, float dV) // H is rolled over, S and V are clamped, all [0,1)
|
||||
{
|
||||
int dHi = (int)(dH*384.0f);
|
||||
int dSi = (int)(dS*255.0f);
|
||||
int dVi = (int)(dV*255.0f);
|
||||
return LICE_AlterColorHSV_int(color, dHi, dSi, dVi);
|
||||
}
|
||||
|
||||
void LICE_AlterBitmapHSV(LICE_IBitmap* src, float dH, float dS, float dV) // H is rolled over, S and V are clamped
|
||||
{
|
||||
if (src) LICE_AlterRectHSV(src,0,0,src->getWidth(),src->getHeight(),dH,dS,dV);
|
||||
}
|
||||
|
||||
void LICE_AlterRectHSV(LICE_IBitmap* src, int xpos, int ypos, int w, int h, float dH, float dS, float dV, int mode) // H is rolled over, S and V are clamped
|
||||
{
|
||||
if (!src) return;
|
||||
|
||||
int destbm_w = src->getWidth(), destbm_h = src->getHeight();
|
||||
const int __sc = (int)src->Extended(LICE_EXT_GET_SCALING,NULL);
|
||||
if (__sc>0)
|
||||
{
|
||||
__LICE_SCU(destbm_w);
|
||||
__LICE_SCU(destbm_h);
|
||||
if (!(mode & LICE_BLIT_IGNORE_SCALING))
|
||||
{
|
||||
__LICE_SC(w);
|
||||
__LICE_SC(h);
|
||||
__LICE_SC(xpos);
|
||||
__LICE_SC(ypos);
|
||||
}
|
||||
}
|
||||
|
||||
if (xpos < 0) {
|
||||
w += xpos;
|
||||
xpos = 0;
|
||||
}
|
||||
if (ypos < 0) {
|
||||
h += ypos;
|
||||
ypos = 0;
|
||||
}
|
||||
|
||||
const int span = src->getRowSpan();
|
||||
if (span < 1 || w < 1 || h < 1 || xpos >= destbm_w || ypos >= destbm_h) return;
|
||||
|
||||
if (w > destbm_w - xpos) w = destbm_w - xpos;
|
||||
if (h > destbm_h - ypos) h = destbm_h - ypos;
|
||||
|
||||
LICE_pixel* px = src->getBits()+ypos*span+xpos;
|
||||
|
||||
int dHi = (int)(dH*384.0f);
|
||||
int dSi = (int)(dS*255.0f);
|
||||
int dVi = (int)(dV*255.0f);
|
||||
if (dHi > 383) dHi=383;
|
||||
else if (dHi < -383) dHi=-383;
|
||||
|
||||
|
||||
if (!dHi && !dSi && !dVi) return; // no mod
|
||||
|
||||
if (w*h > 8192)
|
||||
{
|
||||
// generate a table of HSV translations with clip/clamp
|
||||
unsigned char stab[256], vtab[256];
|
||||
short htab[384];
|
||||
int x;
|
||||
for(x=0;x<256;x++)
|
||||
{
|
||||
int a=x+dSi;
|
||||
if(a<0)a=0; else if (a>255)a=255;
|
||||
stab[x]=a;
|
||||
|
||||
a=x+dVi;
|
||||
if(a<0)a=0; else if (a>255)a=255;
|
||||
vtab[x]=a;
|
||||
|
||||
a=x+dHi;
|
||||
if(a<0)a+=384; else if (a>=384)a-=384;
|
||||
htab[x]=a;
|
||||
}
|
||||
for(;x<384;x++)
|
||||
{
|
||||
int a=x+dHi;
|
||||
if(a<0)a+=384; else if (a>=384)a-=384;
|
||||
htab[x]=a;
|
||||
}
|
||||
|
||||
while (h-->0)
|
||||
{
|
||||
LICE_pixel* tpx = px;
|
||||
px+=span;
|
||||
int xi=w;
|
||||
while (xi-->0)
|
||||
{
|
||||
LICE_pixel color = *tpx;
|
||||
int hh,s,v;
|
||||
LICE_RGB2HSV(LICE_GETR(color), LICE_GETG(color), LICE_GETB(color), &hh, &s, &v);
|
||||
*tpx++ = LICE_HSV2Pix(htab[hh],stab[s],vtab[v],LICE_GETA(color));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (h-->0)
|
||||
{
|
||||
LICE_pixel* tpx = px;
|
||||
px+=span;
|
||||
int xi=w;
|
||||
while (xi-->0)
|
||||
{
|
||||
*tpx = LICE_AlterColorHSV_int(*tpx, dHi, dSi, dVi);
|
||||
tpx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
846
oversampling/WDL/lice/lice_combine.h
Normal file
846
oversampling/WDL/lice/lice_combine.h
Normal file
@@ -0,0 +1,846 @@
|
||||
#ifndef _LICE_COMBINE_H_
|
||||
#define _LICE_COMBINE_H_
|
||||
|
||||
#include "../wdltypes.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable:4244) // float-to-int
|
||||
#endif
|
||||
|
||||
#define __LICE_BOUND(x,lo,hi) ((x)<(lo)?(lo):((x)>(hi)?(hi):(x)))
|
||||
|
||||
|
||||
#define LICE_PIXEL_HALF(x) (((x)>>1)&0x7F7F7F7F)
|
||||
#define LICE_PIXEL_QUARTER(x) (((x)>>2)&0x3F3F3F3F)
|
||||
#define LICE_PIXEL_EIGHTH(x) (((x)>>3)&0x1F1F1F1F)
|
||||
|
||||
|
||||
static inline void __LICE_BilinearFilterI(int *r, int *g, int *b, int *a, const LICE_pixel_chan *pin, const LICE_pixel_chan *pinnext, unsigned int xfrac, unsigned int yfrac)
|
||||
{
|
||||
const unsigned int f4=(xfrac*yfrac)>>16;
|
||||
const unsigned int f3=yfrac-f4; // (1.0-xfrac)*yfrac;
|
||||
const unsigned int f2=xfrac-f4; // xfrac*(1.0-yfrac);
|
||||
const unsigned int f1=65536-yfrac-xfrac+f4; // (1.0-xfrac)*(1.0-yfrac);
|
||||
#define DOCHAN(output, inchan) \
|
||||
(output)=(pin[(inchan)]*f1 + pin[4+(inchan)]*f2 + pinnext[(inchan)]*f3 + pinnext[4+(inchan)]*f4)>>16;
|
||||
DOCHAN(*r,LICE_PIXEL_R)
|
||||
DOCHAN(*g,LICE_PIXEL_G)
|
||||
DOCHAN(*b,LICE_PIXEL_B)
|
||||
DOCHAN(*a,LICE_PIXEL_A)
|
||||
#undef DOCHAN
|
||||
}
|
||||
|
||||
static inline void __LICE_BilinearFilterIPixOut(LICE_pixel_chan *out, const LICE_pixel_chan *pin, const LICE_pixel_chan *pinnext, unsigned int xfrac, unsigned int yfrac)
|
||||
{
|
||||
const unsigned int f4=(xfrac*yfrac)>>16;
|
||||
const unsigned int f3=yfrac-f4; // (1.0-xfrac)*yfrac;
|
||||
const unsigned int f2=xfrac-f4; // xfrac*(1.0-yfrac);
|
||||
const unsigned int f1=65536-yfrac-xfrac+f4; // (1.0-xfrac)*(1.0-yfrac);
|
||||
#define DOCHAN(inchan) \
|
||||
(out[inchan])=(pin[(inchan)]*f1 + pin[4+(inchan)]*f2 + pinnext[(inchan)]*f3 + pinnext[4+(inchan)]*f4)>>16;
|
||||
DOCHAN(LICE_PIXEL_R)
|
||||
DOCHAN(LICE_PIXEL_G)
|
||||
DOCHAN(LICE_PIXEL_B)
|
||||
DOCHAN(LICE_PIXEL_A)
|
||||
#undef DOCHAN
|
||||
}
|
||||
|
||||
|
||||
static inline void __LICE_BilinearFilterI_2(int *r, int *g, int *b, int *a, const LICE_pixel_chan *pin, const LICE_pixel_chan *pinnext, int npoffs, unsigned int xfrac, unsigned int yfrac)
|
||||
{
|
||||
const unsigned int f4=(xfrac*yfrac)>>16;
|
||||
const unsigned int f3=yfrac-f4; // (1.0-xfrac)*yfrac;
|
||||
const unsigned int f2=xfrac-f4; // xfrac*(1.0-yfrac);
|
||||
const unsigned int f1=65536-yfrac-xfrac+f4; // (1.0-xfrac)*(1.0-yfrac);
|
||||
*r=(pin[LICE_PIXEL_R]*f1 + pin[npoffs+LICE_PIXEL_R]*f2 + pinnext[LICE_PIXEL_R]*f3 + pinnext[npoffs+LICE_PIXEL_R]*f4)>>16;
|
||||
*g=(pin[LICE_PIXEL_G]*f1 + pin[npoffs+LICE_PIXEL_G]*f2 + pinnext[LICE_PIXEL_G]*f3 + pinnext[npoffs+LICE_PIXEL_G]*f4)>>16;
|
||||
*b=(pin[LICE_PIXEL_B]*f1 + pin[npoffs+LICE_PIXEL_B]*f2 + pinnext[LICE_PIXEL_B]*f3 + pinnext[npoffs+LICE_PIXEL_B]*f4)>>16;
|
||||
*a=(pin[LICE_PIXEL_A]*f1 + pin[npoffs+LICE_PIXEL_A]*f2 + pinnext[LICE_PIXEL_A]*f3 + pinnext[npoffs+LICE_PIXEL_A]*f4)>>16;
|
||||
}
|
||||
|
||||
|
||||
static inline void __LICE_LinearFilterI(int *r, int *g, int *b, int *a, const LICE_pixel_chan *pin, const LICE_pixel_chan *pinnext, unsigned int frac)
|
||||
{
|
||||
const unsigned int f=65536-frac;
|
||||
*r=(pin[LICE_PIXEL_R]*f + pinnext[LICE_PIXEL_R]*frac)>>16;
|
||||
*g=(pin[LICE_PIXEL_G]*f + pinnext[LICE_PIXEL_G]*frac)>>16;
|
||||
*b=(pin[LICE_PIXEL_B]*f + pinnext[LICE_PIXEL_B]*frac)>>16;
|
||||
*a=(pin[LICE_PIXEL_A]*f + pinnext[LICE_PIXEL_A]*frac)>>16;
|
||||
}
|
||||
static inline void __LICE_LinearFilterIPixOut(LICE_pixel_chan *out, const LICE_pixel_chan *pin, const LICE_pixel_chan *pinnext, unsigned int frac)
|
||||
{
|
||||
const unsigned int f=65536-frac;
|
||||
out[LICE_PIXEL_R]=(pin[LICE_PIXEL_R]*f + pinnext[LICE_PIXEL_R]*frac)>>16;
|
||||
out[LICE_PIXEL_G]=(pin[LICE_PIXEL_G]*f + pinnext[LICE_PIXEL_G]*frac)>>16;
|
||||
out[LICE_PIXEL_B]=(pin[LICE_PIXEL_B]*f + pinnext[LICE_PIXEL_B]*frac)>>16;
|
||||
out[LICE_PIXEL_A]=(pin[LICE_PIXEL_A]*f + pinnext[LICE_PIXEL_A]*frac)>>16;
|
||||
}
|
||||
|
||||
static void inline _LICE_MakePixelClamp(LICE_pixel_chan *out, int r, int g, int b, int a)
|
||||
{
|
||||
#define LICE_PIX_MAKECHAN(a,b) out[a] = (b&~0xff) ? (b<0?0:255) : b;
|
||||
LICE_PIX_MAKECHAN(LICE_PIXEL_B,b)
|
||||
LICE_PIX_MAKECHAN(LICE_PIXEL_G,g)
|
||||
LICE_PIX_MAKECHAN(LICE_PIXEL_R,r)
|
||||
LICE_PIX_MAKECHAN(LICE_PIXEL_A,a)
|
||||
#undef LICE_PIX_MAKECHAN
|
||||
}
|
||||
|
||||
static void inline _LICE_MakePixelNoClamp(LICE_pixel_chan *out, LICE_pixel_chan r, LICE_pixel_chan g, LICE_pixel_chan b, LICE_pixel_chan a)
|
||||
{
|
||||
#define LICE_PIX_MAKECHAN(a,b) out[a] = b;
|
||||
LICE_PIX_MAKECHAN(LICE_PIXEL_B,b)
|
||||
LICE_PIX_MAKECHAN(LICE_PIXEL_G,g)
|
||||
LICE_PIX_MAKECHAN(LICE_PIXEL_R,r)
|
||||
LICE_PIX_MAKECHAN(LICE_PIXEL_A,a)
|
||||
#undef LICE_PIX_MAKECHAN
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define HSV_P v*(256-s)/256
|
||||
#define HSV_Q(hval) v*(16384-(hval)*s)/16384
|
||||
#define HSV_T(hval) v*(16384-(64-(hval))*s)/16384
|
||||
#define HSV_X v
|
||||
extern unsigned short _LICE_RGB2HSV_invtab[256]; // 65536/idx - 1
|
||||
|
||||
#ifdef LICE_COMBINE_IMPLEMENT_HSV
|
||||
LICE_pixel LICE_HSV2Pix(int h, int s, int v, int alpha)
|
||||
#define __LICE_HSV2Pix LICE_HSV2Pix
|
||||
#else
|
||||
static inline LICE_pixel __LICE_HSV2Pix(int h, int s, int v, int alpha)
|
||||
#endif
|
||||
{
|
||||
if (h<192)
|
||||
{
|
||||
if (h<64) return LICE_RGBA(HSV_X,HSV_T(h),HSV_P,alpha);
|
||||
if (h<128) return LICE_RGBA(HSV_Q(h-64),HSV_X,HSV_P,alpha);
|
||||
return LICE_RGBA(HSV_P,HSV_X,HSV_T(h-128),alpha);
|
||||
}
|
||||
if (h < 256) return LICE_RGBA(HSV_P,HSV_Q(h-192),HSV_X,alpha);
|
||||
if (h < 320) return LICE_RGBA(HSV_T(h-256),HSV_P,HSV_X,alpha);
|
||||
return LICE_RGBA(HSV_X,HSV_P,HSV_Q(h-320),alpha);
|
||||
}
|
||||
|
||||
#ifdef LICE_COMBINE_IMPLEMENT_HSV
|
||||
void LICE_HSV2RGB(int h, int s, int v, int* r, int* g, int* b)
|
||||
#define __LICE_HSV2RGB LICE_HSV2RGB
|
||||
#else
|
||||
static inline void __LICE_HSV2RGB(int h, int s, int v, int* r, int* g, int* b)
|
||||
#endif
|
||||
{
|
||||
if (h<192)
|
||||
{
|
||||
if (h<64)
|
||||
{
|
||||
*r = HSV_X; *g = HSV_T(h); *b = HSV_P;
|
||||
}
|
||||
else if (h<128)
|
||||
{
|
||||
*r = HSV_Q(h-64); *g = HSV_X; *b = HSV_P;
|
||||
}
|
||||
else
|
||||
{
|
||||
*r = HSV_P; *g = HSV_X; *b = HSV_T(h-128);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (h < 256)
|
||||
{
|
||||
*r = HSV_P; *g = HSV_Q(h-192); *b = HSV_X;
|
||||
}
|
||||
else if (h < 320)
|
||||
{
|
||||
*r = HSV_T(h-256); *g = HSV_P; *b = HSV_X;
|
||||
}
|
||||
else
|
||||
{
|
||||
*r = HSV_X; *g = HSV_P; *b = HSV_Q(h-320);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define LICE_RGB2HSV_USE_TABLE
|
||||
// h = [0,384), s and v = [0,256)
|
||||
|
||||
#ifdef LICE_COMBINE_IMPLEMENT_HSV
|
||||
void LICE_RGB2HSV(int r, int g, int b, int* h, int* s, int* v)
|
||||
#define __LICE_RGB2HSV LICE_RGB2HSV
|
||||
#else
|
||||
static inline void __LICE_RGB2HSV(int r, int g, int b, int* h, int* s, int* v)
|
||||
#endif
|
||||
{
|
||||
|
||||
// this makes it just 3 conditional branches per call
|
||||
int df,d,maxrgb;
|
||||
int degoffs;
|
||||
if (g > r)
|
||||
{
|
||||
if (g>b) // green max
|
||||
{
|
||||
maxrgb=g;
|
||||
degoffs=128;
|
||||
df = maxrgb - lice_min(b,r);
|
||||
d=b-r;
|
||||
}
|
||||
else // blue max
|
||||
{
|
||||
maxrgb=b;
|
||||
degoffs=256;
|
||||
df = maxrgb - lice_min(g,r);
|
||||
d=r-g;
|
||||
}
|
||||
}
|
||||
else // r >= g
|
||||
{
|
||||
if (r > b) // red max
|
||||
{
|
||||
maxrgb=r;
|
||||
|
||||
if (g<b)
|
||||
{
|
||||
degoffs=383; // not technically correct, but close enough (and simplifies the rounding case -- if you want more accuracy, set to 384,
|
||||
// then add a if (*h == 384) *h=0; after the *h assignment below
|
||||
df = maxrgb - g;
|
||||
}
|
||||
else
|
||||
{
|
||||
degoffs=0;
|
||||
df = maxrgb - b;
|
||||
}
|
||||
d=g-b;
|
||||
}
|
||||
else // blue max
|
||||
{
|
||||
maxrgb=b;
|
||||
degoffs=256;
|
||||
df = maxrgb - lice_min(g,r);
|
||||
d=r-g;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*v = maxrgb;
|
||||
#ifndef LICE_RGB2HSV_USE_TABLE // table mode doesnt need this check
|
||||
if (!df) {
|
||||
*h = *s = 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
|
||||
#ifdef LICE_RGB2HSV_USE_TABLE
|
||||
|
||||
|
||||
*h = (d*((int)(_LICE_RGB2HSV_invtab[df]+1)))/1024 + degoffs;
|
||||
*s = (df*((int)_LICE_RGB2HSV_invtab[maxrgb]))/256;
|
||||
#else
|
||||
*h = ((d*64)/df) + degoffs;
|
||||
*s = (df*256)/(maxrgb+1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha) // alpha is ignored.
|
||||
// generally speaking, the "a" is 0-255, and alpha is 0-256/1-256.
|
||||
|
||||
// Optimization when a=255 and alpha=1.0f, useful for doing a big vector drawn fill or something.
|
||||
// This could be called _LICE_PutPixel but that would probably be confusing.
|
||||
class _LICE_CombinePixelsClobberNoClamp
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha) // alpha is ignored.
|
||||
{
|
||||
_LICE_MakePixelNoClamp(dest, r, g, b, a);
|
||||
}
|
||||
};
|
||||
|
||||
class _LICE_CombinePixelsClobberClamp
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha) // alpha is ignored.
|
||||
{
|
||||
_LICE_MakePixelClamp(dest, r, g, b, a);
|
||||
}
|
||||
};
|
||||
|
||||
class _LICE_CombinePixelsClobberFAST
|
||||
{
|
||||
public:
|
||||
static inline void doPixFAST(LICE_pixel *dest, LICE_pixel src) // alpha is ignored.
|
||||
{
|
||||
*dest = src;
|
||||
}
|
||||
};
|
||||
|
||||
class _LICE_CombinePixelsHalfMixNoClamp
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
_LICE_MakePixelNoClamp(dest,
|
||||
(dest[LICE_PIXEL_R]+r)>>1,
|
||||
(dest[LICE_PIXEL_G]+g)>>1,
|
||||
(dest[LICE_PIXEL_B]+b)>>1,
|
||||
(dest[LICE_PIXEL_A]+a)>>1);
|
||||
}
|
||||
};
|
||||
|
||||
class _LICE_CombinePixelsHalfMixFAST
|
||||
{
|
||||
public:
|
||||
static inline void doPixFAST(LICE_pixel *dest, LICE_pixel src) // src is full range
|
||||
{
|
||||
*dest = ((*dest>>1) &0x7f7f7f7f) + ((src>>1)&0x7f7f7f7f);
|
||||
}
|
||||
};
|
||||
|
||||
class _LICE_CombinePixelsHalfMixClamp
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
_LICE_MakePixelClamp(dest,
|
||||
(dest[LICE_PIXEL_R]+r)>>1,
|
||||
(dest[LICE_PIXEL_G]+g)>>1,
|
||||
(dest[LICE_PIXEL_B]+b)>>1,
|
||||
(dest[LICE_PIXEL_A]+a)>>1);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class _LICE_CombinePixelsHalfMix2FAST
|
||||
{
|
||||
public:
|
||||
static inline void doPixFAST(LICE_pixel *dest, LICE_pixel src) // src is pre-halfed and masked
|
||||
{
|
||||
*dest = ((*dest>>1) &0x7f7f7f7f) + src;
|
||||
}
|
||||
};
|
||||
|
||||
class _LICE_CombinePixelsQuarterMix2FAST
|
||||
{
|
||||
public:
|
||||
static inline void doPixFAST(LICE_pixel *dest, LICE_pixel src) // src is pre-quartered and masked
|
||||
{
|
||||
LICE_pixel tmp = *dest;
|
||||
*dest = ((tmp>>1) &0x7f7f7f7f) + ((tmp>>2) &0x3f3f3f3f) + src;
|
||||
}
|
||||
};
|
||||
|
||||
class _LICE_CombinePixelsThreeEighthMix2FAST
|
||||
{
|
||||
public:
|
||||
static inline void doPixFAST(LICE_pixel *dest, LICE_pixel src) // src is pre-three-eighthed and masked
|
||||
{
|
||||
LICE_pixel tmp = *dest;
|
||||
*dest = ((tmp>>1) &0x7f7f7f7f) + ((tmp>>3) &0x1f1f1f1f) + src;
|
||||
}
|
||||
};
|
||||
|
||||
class _LICE_CombinePixelsThreeQuarterMix2FAST
|
||||
{
|
||||
public:
|
||||
static inline void doPixFAST(LICE_pixel *dest, LICE_pixel src) // src is pre-three-quartered and masked
|
||||
{
|
||||
*dest = ((*dest>>2) &0x3f3f3f3f) + src;
|
||||
}
|
||||
};
|
||||
|
||||
class _LICE_CombinePixelsCopyNoClamp
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
const int sc=(256-alpha);
|
||||
|
||||
// don't check alpha=0 here, since the caller should (since alpha is usually used for static alphas)
|
||||
_LICE_MakePixelNoClamp(dest,
|
||||
r + ((dest[LICE_PIXEL_R]-r)*sc)/256,
|
||||
g + ((dest[LICE_PIXEL_G]-g)*sc)/256,
|
||||
b + ((dest[LICE_PIXEL_B]-b)*sc)/256,
|
||||
a + ((dest[LICE_PIXEL_A]-a)*sc)/256);
|
||||
}
|
||||
};
|
||||
|
||||
class _LICE_CombinePixelsCopyClamp
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
const int sc=(256-alpha);
|
||||
|
||||
// don't check alpha=0 here, since the caller should (since alpha is usually used for static alphas)
|
||||
_LICE_MakePixelClamp(dest,
|
||||
r + ((dest[LICE_PIXEL_R]-r)*sc)/256,
|
||||
g + ((dest[LICE_PIXEL_G]-g)*sc)/256,
|
||||
b + ((dest[LICE_PIXEL_B]-b)*sc)/256,
|
||||
a + ((dest[LICE_PIXEL_A]-a)*sc)/256);
|
||||
}
|
||||
};
|
||||
|
||||
class _LICE_CombinePixelsCopySourceAlphaNoClamp
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
if (a)
|
||||
{
|
||||
const int sc2=(alpha*(a+1))/256;
|
||||
const int sc = 256 - sc2;
|
||||
|
||||
_LICE_MakePixelNoClamp(dest,
|
||||
r + ((dest[LICE_PIXEL_R]-r)*sc)/256,
|
||||
g + ((dest[LICE_PIXEL_G]-g)*sc)/256,
|
||||
b + ((dest[LICE_PIXEL_B]-b)*sc)/256,
|
||||
lice_min(255,sc2 + dest[LICE_PIXEL_A]));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class _LICE_CombinePixelsCopySourceAlphaClamp
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
if (a)
|
||||
{
|
||||
const int sc2=(alpha*(a+1))/256;
|
||||
const int sc = 256 - sc2;
|
||||
|
||||
_LICE_MakePixelClamp(dest,
|
||||
r + ((dest[LICE_PIXEL_R]-r)*sc)/256,
|
||||
g + ((dest[LICE_PIXEL_G]-g)*sc)/256,
|
||||
b + ((dest[LICE_PIXEL_B]-b)*sc)/256,
|
||||
sc2 + dest[LICE_PIXEL_A]);
|
||||
}
|
||||
}
|
||||
};
|
||||
class _LICE_CombinePixelsCopySourceAlphaIgnoreAlphaParmNoClamp
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
if (a)
|
||||
{
|
||||
if (a==255)
|
||||
{
|
||||
_LICE_MakePixelNoClamp(dest,r,g,b,a);
|
||||
}
|
||||
else
|
||||
{
|
||||
const int sc=(255-a);
|
||||
|
||||
_LICE_MakePixelNoClamp(dest,
|
||||
r + ((dest[LICE_PIXEL_R]-r)*sc)/256,
|
||||
g + ((dest[LICE_PIXEL_G]-g)*sc)/256,
|
||||
b + ((dest[LICE_PIXEL_B]-b)*sc)/256,
|
||||
lice_min(255,a + dest[LICE_PIXEL_A]));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
class _LICE_CombinePixelsCopySourceAlphaIgnoreAlphaParmClamp
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
if (a)
|
||||
{
|
||||
if (a==255)
|
||||
{
|
||||
_LICE_MakePixelClamp(dest,r,g,b,a);
|
||||
}
|
||||
else
|
||||
{
|
||||
const int sc=(255-a);
|
||||
|
||||
_LICE_MakePixelClamp(dest,
|
||||
r + ((dest[LICE_PIXEL_R]-r)*sc)/256,
|
||||
g + ((dest[LICE_PIXEL_G]-g)*sc)/256,
|
||||
b + ((dest[LICE_PIXEL_B]-b)*sc)/256,
|
||||
a + dest[LICE_PIXEL_A]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef LICE_DISABLE_BLEND_ADD
|
||||
|
||||
class _LICE_CombinePixelsAdd
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
// don't check alpha=0 here, since the caller should (since alpha is usually used for static alphas)
|
||||
|
||||
_LICE_MakePixelClamp(dest,
|
||||
dest[LICE_PIXEL_R]+(r*alpha)/256,
|
||||
dest[LICE_PIXEL_G]+(g*alpha)/256,
|
||||
dest[LICE_PIXEL_B]+(b*alpha)/256,
|
||||
dest[LICE_PIXEL_A]+(a*alpha)/256);
|
||||
|
||||
}
|
||||
};
|
||||
class _LICE_CombinePixelsAddSourceAlpha
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
if (a)
|
||||
{
|
||||
alpha=(alpha*(a+1))/256;
|
||||
_LICE_MakePixelClamp(dest,
|
||||
dest[LICE_PIXEL_R]+(r*alpha)/256,
|
||||
dest[LICE_PIXEL_G]+(g*alpha)/256,
|
||||
dest[LICE_PIXEL_B]+(b*alpha)/256,
|
||||
dest[LICE_PIXEL_A]+(a*alpha)/256);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#else // !LICE_DISABLE_BLEND_ADD
|
||||
#define _LICE_CombinePixelsAddSourceAlpha _LICE_CombinePixelsCopySourceAlphaClamp
|
||||
#define _LICE_CombinePixelsAdd _LICE_CombinePixelsCopyClamp
|
||||
#endif
|
||||
|
||||
#ifndef LICE_DISABLE_BLEND_DODGE
|
||||
|
||||
class _LICE_CombinePixelsColorDodge
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
const int src_r = 256-r*alpha/256;
|
||||
const int src_g = 256-g*alpha/256;
|
||||
const int src_b = 256-b*alpha/256;
|
||||
const int src_a = 256-a*alpha/256;
|
||||
|
||||
_LICE_MakePixelClamp(dest,
|
||||
src_r > 1 ? 256*dest[LICE_PIXEL_R] / src_r : 256*dest[LICE_PIXEL_R],
|
||||
src_g > 1 ? 256*dest[LICE_PIXEL_G] / src_g : 256*dest[LICE_PIXEL_G],
|
||||
src_b > 1 ? 256*dest[LICE_PIXEL_B] / src_b : 256*dest[LICE_PIXEL_B],
|
||||
src_a > 1 ? 256*dest[LICE_PIXEL_A] / src_a : 256*dest[LICE_PIXEL_A]);
|
||||
}
|
||||
};
|
||||
|
||||
class _LICE_CombinePixelsColorDodgeSourceAlpha
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
const int ualpha=(alpha*(a+1))/256;
|
||||
|
||||
const int src_r = 256-r*ualpha/256;
|
||||
const int src_g = 256-g*ualpha/256;
|
||||
const int src_b = 256-b*ualpha/256;
|
||||
const int src_a = 256-a*ualpha/256;
|
||||
|
||||
_LICE_MakePixelClamp(dest,
|
||||
src_r > 1 ? 256*dest[LICE_PIXEL_R] / src_r : 256*dest[LICE_PIXEL_R],
|
||||
src_g > 1 ? 256*dest[LICE_PIXEL_G] / src_g : 256*dest[LICE_PIXEL_G],
|
||||
src_b > 1 ? 256*dest[LICE_PIXEL_B] / src_b : 256*dest[LICE_PIXEL_B],
|
||||
src_a > 1 ? 256*dest[LICE_PIXEL_A] / src_a : 256*dest[LICE_PIXEL_A]);
|
||||
}
|
||||
};
|
||||
|
||||
#else // !LICE_DISABLE_BLEND_DODGE
|
||||
#define _LICE_CombinePixelsColorDodgeSourceAlpha _LICE_CombinePixelsCopySourceAlphaClamp
|
||||
#define _LICE_CombinePixelsColorDodge _LICE_CombinePixelsCopyClamp
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef LICE_DISABLE_BLEND_MUL
|
||||
|
||||
class _LICE_CombinePixelsMulNoClamp
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
// we could check alpha=0 here, but the caller should (since alpha is usually used for static alphas)
|
||||
|
||||
const int da=(256-alpha)*256;
|
||||
_LICE_MakePixelNoClamp(dest,
|
||||
(dest[LICE_PIXEL_R]*(da + (r*alpha)))>>16,
|
||||
(dest[LICE_PIXEL_G]*(da + (g*alpha)))>>16,
|
||||
(dest[LICE_PIXEL_B]*(da + (b*alpha)))>>16,
|
||||
(dest[LICE_PIXEL_A]*(da + (a*alpha)))>>16);
|
||||
|
||||
}
|
||||
};
|
||||
class _LICE_CombinePixelsMulClamp
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
// we could check alpha=0 here, but the caller should (since alpha is usually used for static alphas)
|
||||
|
||||
const int da=(256-alpha)*256;
|
||||
_LICE_MakePixelClamp(dest,
|
||||
(dest[LICE_PIXEL_R]*(da + (r*alpha)))>>16,
|
||||
(dest[LICE_PIXEL_G]*(da + (g*alpha)))>>16,
|
||||
(dest[LICE_PIXEL_B]*(da + (b*alpha)))>>16,
|
||||
(dest[LICE_PIXEL_A]*(da + (a*alpha)))>>16);
|
||||
|
||||
}
|
||||
};
|
||||
class _LICE_CombinePixelsMulSourceAlphaNoClamp
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
if (a)
|
||||
{
|
||||
const int ualpha=(alpha*(a+1))/256;
|
||||
const int da=(256-ualpha)*256;
|
||||
_LICE_MakePixelNoClamp(dest,
|
||||
(dest[LICE_PIXEL_R]*(da + (r*ualpha)))>>16,
|
||||
(dest[LICE_PIXEL_G]*(da + (g*ualpha)))>>16,
|
||||
(dest[LICE_PIXEL_B]*(da + (b*ualpha)))>>16,
|
||||
(dest[LICE_PIXEL_A]*(da + (a*ualpha)))>>16);
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
class _LICE_CombinePixelsMulSourceAlphaClamp
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
if (a)
|
||||
{
|
||||
const int ualpha=(alpha*(a+1))/256;
|
||||
const int da=(256-ualpha)*256;
|
||||
_LICE_MakePixelClamp(dest,
|
||||
(dest[LICE_PIXEL_R]*(da + (r*ualpha)))>>16,
|
||||
(dest[LICE_PIXEL_G]*(da + (g*ualpha)))>>16,
|
||||
(dest[LICE_PIXEL_B]*(da + (b*ualpha)))>>16,
|
||||
(dest[LICE_PIXEL_A]*(da + (a*ualpha)))>>16);
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#else // !LICE_DISABLE_BLEND_MUL
|
||||
#define _LICE_CombinePixelsMulSourceAlphaNoClamp _LICE_CombinePixelsCopySourceAlphaNoClamp
|
||||
#define _LICE_CombinePixelsMulSourceAlphaClamp _LICE_CombinePixelsCopySourceAlphaClamp
|
||||
#define _LICE_CombinePixelsMulNoClamp _LICE_CombinePixelsCopyNoClamp
|
||||
#define _LICE_CombinePixelsMulClamp _LICE_CombinePixelsCopyClamp
|
||||
#endif
|
||||
|
||||
//#define LICE_DISABLE_BLEND_OVERLAY
|
||||
#ifndef LICE_DISABLE_BLEND_OVERLAY
|
||||
|
||||
class _LICE_CombinePixelsOverlay
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
// we could check alpha=0 here, but the caller should (since alpha is usually used for static alphas)
|
||||
|
||||
int destr = dest[LICE_PIXEL_R], destg = dest[LICE_PIXEL_G], destb = dest[LICE_PIXEL_B], desta = dest[LICE_PIXEL_A];
|
||||
|
||||
#if 0
|
||||
int srcr = r*alpha, srcg = g*alpha, srcb = b*alpha, srca = a*alpha;
|
||||
int da=(256-alpha)*256;
|
||||
int mr = (destr*(da+srcr))/65536;
|
||||
int mg = (destg*(da+srcg))/65536;
|
||||
int mb = (destb*(da+srcb))/65536;
|
||||
int ma = (desta*(da+srca))/65536;
|
||||
int sr = 256-(65536-srcr)*(256-destr)/65536;
|
||||
int sg = 256-(65536-srcg)*(256-destg)/65536;
|
||||
int sb = 256-(65536-srcb)*(256-destb)/65536;
|
||||
int sa = 256-(65536-srca)*(256-desta)/65536;
|
||||
|
||||
destr = (destr*sr+(256-destr)*mr)/256;
|
||||
destg = (destg*sg+(256-destg)*mg)/256;
|
||||
destb = (destb*sb+(256-destb)*mb)/256;
|
||||
desta = (desta*sa+(256-desta)*ma)/256;
|
||||
#else
|
||||
// can produce slightly diff (+-1) results from above due to rounding
|
||||
const int da=(256-alpha)*128;
|
||||
const int srcr = r*alpha+da, srcg = g*alpha+da, srcb = b*alpha+da, srca = a*alpha + da;
|
||||
destr = ( destr*( (destr*(32768-srcr))/256 + srcr ) ) >> 15;
|
||||
destg = ( destg*( (destg*(32768-srcg))/256 + srcg ) ) >> 15;
|
||||
destb = ( destb*( (destb*(32768-srcb))/256 + srcb ) ) >> 15;
|
||||
desta = ( desta*( (desta*(32768-srca))/256 + srca ) ) >> 15;
|
||||
|
||||
#endif
|
||||
|
||||
_LICE_MakePixelClamp(dest, destr, destg, destb, desta);
|
||||
}
|
||||
};
|
||||
|
||||
class _LICE_CombinePixelsOverlaySourceAlpha
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
_LICE_CombinePixelsOverlay::doPix(dest, r, g, b, a, (alpha*(a+1))/256);
|
||||
}
|
||||
};
|
||||
|
||||
#else // !LICE_DISABLE_BLEND_OVERLAY
|
||||
#define _LICE_CombinePixelsOverlaySourceAlpha _LICE_CombinePixelsCopySourceAlphaClamp
|
||||
#define _LICE_CombinePixelsOverlay _LICE_CombinePixelsCopyClamp
|
||||
#endif
|
||||
|
||||
|
||||
//#define LICE_DISABLE_BLEND_HSVADJ
|
||||
#ifndef LICE_DISABLE_BLEND_HSVADJ
|
||||
|
||||
class _LICE_CombinePixelsHSVAdjust
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
int h,s,v;
|
||||
__LICE_RGB2HSV(dest[LICE_PIXEL_R],dest[LICE_PIXEL_G],dest[LICE_PIXEL_B],&h,&s,&v);
|
||||
h+=(((r+r/2) - 192) * alpha)/256;
|
||||
if (h<0)h+=384;
|
||||
else if (h>=384) h-=384;
|
||||
s+=((g-128)*alpha)/128;
|
||||
if (s&~0xff)
|
||||
{
|
||||
if (s<0)s=0;
|
||||
else s=255;
|
||||
}
|
||||
v+=((b-128)*alpha)/128;
|
||||
if (v&~0xff)
|
||||
{
|
||||
if (v<0)v=0;
|
||||
else v=255;
|
||||
}
|
||||
|
||||
*(LICE_pixel *)dest = __LICE_HSV2Pix(h,s,v,a);
|
||||
}
|
||||
};
|
||||
|
||||
class _LICE_CombinePixelsHSVAdjustSourceAlpha
|
||||
{
|
||||
public:
|
||||
static inline void doPix(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha)
|
||||
{
|
||||
_LICE_CombinePixelsHSVAdjust::doPix(dest, r, g, b, a, (alpha*(a+1))/256);
|
||||
}
|
||||
};
|
||||
|
||||
#else // !LICE_DISABLE_BLEND_HSVADJ
|
||||
#define _LICE_CombinePixelsHSVAdjustSourceAlpha _LICE_CombinePixelsCopySourceAlphaClamp
|
||||
#define _LICE_CombinePixelsHSVAdjust _LICE_CombinePixelsCopyClamp
|
||||
#endif
|
||||
|
||||
// note: the "clamp" parameter would generally be false, unless you're working with
|
||||
// input colors that need to be clamped (i.e. if you have a r value of >255 or <0, etc.
|
||||
// if your input is LICE_pixel only then use false, and it will clamp as needed depending
|
||||
// on the blend mode..
|
||||
|
||||
//#define __LICE__ACTION(comb) templateclass<comb>::function(parameters)
|
||||
//__LICE_ACTION_SRCALPHA(mode,alpha,clamp);
|
||||
//#undef __LICE__ACTION
|
||||
|
||||
|
||||
// use this for paths that support LICE_BLIT_USE_ALPHA (source-alpha combining), but
|
||||
// otherwise have constant alpha
|
||||
#define __LICE_ACTION_SRCALPHA(mode,ia,clamp) \
|
||||
if ((ia)!=0) switch ((mode)&(LICE_BLIT_MODE_MASK|LICE_BLIT_USE_ALPHA)) { \
|
||||
case LICE_BLIT_MODE_COPY: if ((ia)>0) { \
|
||||
if (clamp) { \
|
||||
if ((ia)==256) { __LICE__ACTION(_LICE_CombinePixelsClobberClamp); } \
|
||||
else { __LICE__ACTION(_LICE_CombinePixelsCopyClamp); } \
|
||||
} else { \
|
||||
if ((ia)==256) { __LICE__ACTION(_LICE_CombinePixelsClobberNoClamp); } \
|
||||
else { __LICE__ACTION(_LICE_CombinePixelsCopyNoClamp); } \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
case LICE_BLIT_MODE_ADD: __LICE__ACTION(_LICE_CombinePixelsAdd); break; \
|
||||
case LICE_BLIT_MODE_DODGE: __LICE__ACTION(_LICE_CombinePixelsColorDodge); break; \
|
||||
case LICE_BLIT_MODE_MUL: \
|
||||
if (clamp) { __LICE__ACTION(_LICE_CombinePixelsMulClamp); } \
|
||||
else { __LICE__ACTION(_LICE_CombinePixelsMulNoClamp); } \
|
||||
break; \
|
||||
case LICE_BLIT_MODE_OVERLAY: __LICE__ACTION(_LICE_CombinePixelsOverlay); break; \
|
||||
case LICE_BLIT_MODE_HSVADJ: __LICE__ACTION(_LICE_CombinePixelsHSVAdjust); break; \
|
||||
case LICE_BLIT_MODE_COPY|LICE_BLIT_USE_ALPHA: \
|
||||
if (clamp) { \
|
||||
if ((ia)==256) { __LICE__ACTION(_LICE_CombinePixelsCopySourceAlphaIgnoreAlphaParmClamp);} \
|
||||
else { __LICE__ACTION(_LICE_CombinePixelsCopySourceAlphaClamp); } \
|
||||
} else { \
|
||||
if ((ia)==256) { __LICE__ACTION(_LICE_CombinePixelsCopySourceAlphaIgnoreAlphaParmNoClamp); } \
|
||||
else { __LICE__ACTION(_LICE_CombinePixelsCopySourceAlphaNoClamp); } \
|
||||
} \
|
||||
break; \
|
||||
case LICE_BLIT_MODE_ADD|LICE_BLIT_USE_ALPHA: \
|
||||
__LICE__ACTION(_LICE_CombinePixelsAddSourceAlpha); \
|
||||
break; \
|
||||
case LICE_BLIT_MODE_DODGE|LICE_BLIT_USE_ALPHA: \
|
||||
__LICE__ACTION(_LICE_CombinePixelsColorDodgeSourceAlpha); \
|
||||
break; \
|
||||
case LICE_BLIT_MODE_MUL|LICE_BLIT_USE_ALPHA: \
|
||||
if (clamp) { __LICE__ACTION(_LICE_CombinePixelsMulSourceAlphaClamp); } \
|
||||
else { __LICE__ACTION(_LICE_CombinePixelsMulSourceAlphaNoClamp); } \
|
||||
break; \
|
||||
case LICE_BLIT_MODE_OVERLAY|LICE_BLIT_USE_ALPHA: \
|
||||
__LICE__ACTION(_LICE_CombinePixelsOverlaySourceAlpha); \
|
||||
break; \
|
||||
case LICE_BLIT_MODE_HSVADJ|LICE_BLIT_USE_ALPHA: \
|
||||
__LICE__ACTION(_LICE_CombinePixelsHSVAdjustSourceAlpha); \
|
||||
break; \
|
||||
}
|
||||
|
||||
|
||||
// use this for paths that can have per pixel alpha, but calculate it themselves
|
||||
#define __LICE_ACTION_NOSRCALPHA(mode, ia,clamp) \
|
||||
if ((ia)!=0) switch ((mode)&LICE_BLIT_MODE_MASK) { \
|
||||
case LICE_BLIT_MODE_COPY: if ((ia)>0) { if (clamp) { __LICE__ACTION(_LICE_CombinePixelsCopyClamp); } else { __LICE__ACTION(_LICE_CombinePixelsCopyNoClamp); } } break; \
|
||||
case LICE_BLIT_MODE_ADD: __LICE__ACTION(_LICE_CombinePixelsAdd); break; \
|
||||
case LICE_BLIT_MODE_DODGE: __LICE__ACTION(_LICE_CombinePixelsColorDodge); break; \
|
||||
case LICE_BLIT_MODE_MUL: if (clamp) { __LICE__ACTION(_LICE_CombinePixelsMulClamp); } else { __LICE__ACTION(_LICE_CombinePixelsMulNoClamp); } break; \
|
||||
case LICE_BLIT_MODE_OVERLAY: __LICE__ACTION(_LICE_CombinePixelsOverlay); break; \
|
||||
case LICE_BLIT_MODE_HSVADJ: __LICE__ACTION(_LICE_CombinePixelsHSVAdjust); break; \
|
||||
}
|
||||
|
||||
// For drawing where there is constant alpha and no per-pixel alpha.
|
||||
#define __LICE_ACTION_CONSTANTALPHA(mode,ia,clamp) \
|
||||
if ((ia)!=0) switch ((mode)&LICE_BLIT_MODE_MASK) { \
|
||||
case LICE_BLIT_MODE_COPY: \
|
||||
if ((ia)==256) { if (clamp) { __LICE__ACTION(_LICE_CombinePixelsClobberClamp); } else { __LICE__ACTION(_LICE_CombinePixelsClobberNoClamp); } } \
|
||||
else if ((ia)==128) { if (clamp) { __LICE__ACTION(_LICE_CombinePixelsHalfMixClamp); } else { __LICE__ACTION(_LICE_CombinePixelsHalfMixNoClamp); } } \
|
||||
else if ((ia)>0) { if (clamp) { __LICE__ACTION(_LICE_CombinePixelsCopyClamp); } else { __LICE__ACTION(_LICE_CombinePixelsCopyNoClamp); } } \
|
||||
break; \
|
||||
case LICE_BLIT_MODE_ADD: __LICE__ACTION(_LICE_CombinePixelsAdd); break; \
|
||||
case LICE_BLIT_MODE_DODGE: __LICE__ACTION(_LICE_CombinePixelsColorDodge); break; \
|
||||
case LICE_BLIT_MODE_MUL: if (clamp) { __LICE__ACTION(_LICE_CombinePixelsMulClamp); } else { __LICE__ACTION(_LICE_CombinePixelsMulNoClamp); } break; \
|
||||
case LICE_BLIT_MODE_OVERLAY: __LICE__ACTION(_LICE_CombinePixelsOverlay); break; \
|
||||
case LICE_BLIT_MODE_HSVADJ: __LICE__ACTION(_LICE_CombinePixelsHSVAdjust); break; \
|
||||
}
|
||||
|
||||
typedef void (*LICE_COMBINEFUNC)(LICE_pixel_chan *dest, int r, int g, int b, int a, int alpha);
|
||||
|
||||
static void WDL_STATICFUNC_UNUSED __LICE_SC_INTERNAL(int &x, int __sc) {
|
||||
const WDL_INT64 t = (((WDL_INT64) x*(__sc))/256);
|
||||
x = (int) wdl_clamp(t, -WDL_INT64_CONST(0x80000000), WDL_INT64_CONST(0x7fffffff));
|
||||
}
|
||||
static void __LICE_SCU_INTERNAL(int &x, int __sc) {
|
||||
const WDL_UINT64 t = (((WDL_UINT64) x*(__sc))>>8);
|
||||
x = (unsigned int) wdl_min(t, WDL_UINT64_CONST(0xffffffff));
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || (defined(__APPLE__) && !defined(__LP64__))
|
||||
static void WDL_STATICFUNC_UNUSED __LICE_SC_INTERNAL(LONG &x, int __sc) {
|
||||
const WDL_INT64 t = (((WDL_INT64) x*(__sc))/256);
|
||||
x = (LONG) wdl_clamp(t, -WDL_INT64_CONST(0x80000000), WDL_INT64_CONST(0x7fffffff));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void WDL_STATICFUNC_UNUSED __LICE_SC_INTERNAL(float &x, int __sc) { x = (float) (((double)x * __sc) / 256.0); }
|
||||
static void WDL_STATICFUNC_UNUSED __LICE_SC_INTERNAL(double &x, int __sc) { x = (x * __sc) / 256.0; }
|
||||
|
||||
#define __LICE_SC(x) __LICE_SC_INTERNAL(x,__sc)
|
||||
#define __LICE_SCU(x) __LICE_SCU_INTERNAL(x,__sc)
|
||||
|
||||
#endif // _LICE_COMBINE_H_
|
||||
164
oversampling/WDL/lice/lice_extended.h
Normal file
164
oversampling/WDL/lice/lice_extended.h
Normal file
@@ -0,0 +1,164 @@
|
||||
#ifndef _LICE_EXTENDED_
|
||||
#define _LICE_EXTENDED_
|
||||
|
||||
#include "lice.h"
|
||||
|
||||
#define DISABLE_LICE_EXTENSIONS
|
||||
|
||||
// stuff to pass to LICE_IBitmap::Extended
|
||||
|
||||
enum // IDs
|
||||
{
|
||||
LICE_EXT_SUPPORTS_ID, // data = ID, returns 1 if that extension ID is supported
|
||||
LICE_EXT_CLEAR_ACCEL,
|
||||
LICE_EXT_LINE_ACCEL,
|
||||
LICE_EXT_FILLRECT_ACCEL,
|
||||
LICE_EXT_DRAWCBEZIER_ACCEL,
|
||||
LICE_EXT_DRAWGLYPH_ACCEL,
|
||||
LICE_EXT_BLIT_ACCEL,
|
||||
LICE_EXT_SCALEDBLIT_ACCEL,
|
||||
LICE_EXT_GETFBOTEX_ACCEL, // if the bitmap is implemented as an openGL framebuffer object, get its texture backing store
|
||||
LICE_EXT_DASHEDLINE_ACCEL,
|
||||
LICE_EXT_GETPIXEL_ACCEL,
|
||||
LICE_EXT_PUTPIXEL_ACCEL,
|
||||
LICE_EXT_SETCLIP, // data == 0 to clear clip
|
||||
LICE_EXT_WINDOW_BLIT,
|
||||
LICE_EXT_FORGET, // optimizations can sometimes happen if a bitmap can be told it doesn't need to retain data after it's accessed
|
||||
LICE_EXT_DRAWTRIANGLE_ACCEL,
|
||||
};
|
||||
|
||||
struct LICE_Ext_Line_acceldata
|
||||
{
|
||||
float x1, y1, x2, y2;
|
||||
LICE_pixel color;
|
||||
float alpha;
|
||||
int mode;
|
||||
bool aa;
|
||||
|
||||
LICE_Ext_Line_acceldata(float _x1, float _y1, float _x2, float _y2, LICE_pixel _color, float _alpha, int _mode, bool _aa)
|
||||
: x1(_x1), y1(_y1), x2(_x2), y2(_y2), color(_color), alpha(_alpha), mode(_mode), aa(_aa) {}
|
||||
};
|
||||
|
||||
struct LICE_Ext_FillRect_acceldata
|
||||
{
|
||||
int x, y, w, h;
|
||||
LICE_pixel color;
|
||||
float alpha;
|
||||
int mode;
|
||||
|
||||
LICE_Ext_FillRect_acceldata(int _x, int _y, int _w, int _h, LICE_pixel _color, float _alpha, int _mode)
|
||||
: x(_x), y(_y), w(_w), h(_h), color(_color), alpha(_alpha), mode(_mode) {}
|
||||
};
|
||||
|
||||
struct LICE_Ext_DrawCBezier_acceldata
|
||||
{
|
||||
float xstart, ystart, xctl1, yctl1, xctl2, yctl2, xend, yend;
|
||||
LICE_pixel color;
|
||||
float alpha;
|
||||
int mode;
|
||||
bool aa;
|
||||
|
||||
LICE_Ext_DrawCBezier_acceldata(float _xstart, float _ystart, float _xctl1, float _yctl1, float _xctl2, float _yctl2, float _xend, float _yend,
|
||||
LICE_pixel _color, float _alpha, int _mode, bool _aa)
|
||||
: xstart(_xstart), ystart(_ystart), xctl1(_xctl1), yctl1(_yctl1), xctl2(_xctl2), yctl2(_yctl2), xend(_xend), yend(_yend),
|
||||
color(_color), alpha(_alpha), mode(_mode), aa(_aa) {}
|
||||
};
|
||||
|
||||
struct LICE_Ext_DrawGlyph_acceldata
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
LICE_pixel color;
|
||||
const LICE_pixel_chan* alphas;
|
||||
int glyph_w, glyph_h;
|
||||
float alpha;
|
||||
int mode;
|
||||
|
||||
LICE_Ext_DrawGlyph_acceldata(int _x, int _y, LICE_pixel _color, LICE_pixel_chan* _alphas, int _glyph_w, int _glyph_h, float _alpha, int _mode)
|
||||
: x(_x), y(_y), color(_color), alphas(_alphas), glyph_w(_glyph_w), glyph_h(_glyph_h), alpha(_alpha), mode(_mode) {}
|
||||
};
|
||||
|
||||
struct LICE_Ext_Blit_acceldata
|
||||
{
|
||||
LICE_IBitmap* src;
|
||||
int dstx, dsty, srcx, srcy, srcw, srch;
|
||||
float alpha;
|
||||
int mode;
|
||||
|
||||
LICE_Ext_Blit_acceldata(LICE_IBitmap* _src, int _dstx, int _dsty, int _srcx, int _srcy, int _srcw, int _srch, float _alpha, int _mode)
|
||||
: src(_src), dstx(_dstx), dsty(_dsty), srcx(_srcx), srcy(_srcy), srcw(_srcw), srch(_srch), alpha(_alpha), mode(_mode) {}
|
||||
};
|
||||
|
||||
struct LICE_Ext_ScaledBlit_acceldata
|
||||
{
|
||||
LICE_IBitmap* src;
|
||||
int dstx, dsty, dstw, dsth;
|
||||
float srcx, srcy, srcw, srch;
|
||||
float alpha;
|
||||
int mode;
|
||||
|
||||
LICE_Ext_ScaledBlit_acceldata(LICE_IBitmap* _src, int _dstx, int _dsty, int _dstw, int _dsth, float _srcx, float _srcy, float _srcw, float _srch, float _alpha, int _mode)
|
||||
: src(_src), dstx(_dstx), dsty(_dsty), dstw(_dstw), dsth(_dsth), srcx(_srcx), srcy(_srcy), srcw(_srcw), srch(_srch), alpha(_alpha), mode(_mode) {}
|
||||
};
|
||||
|
||||
struct LICE_Ext_DashedLine_acceldata
|
||||
{
|
||||
float x1, y1, x2, y2;
|
||||
int pxon, pxoff;
|
||||
LICE_pixel color;
|
||||
float alpha;
|
||||
int mode;
|
||||
bool aa;
|
||||
|
||||
LICE_Ext_DashedLine_acceldata(float _x1, float _y1, float _x2, float _y2, int _pxon, int _pxoff, LICE_pixel _color, float _alpha, int _mode, bool _aa)
|
||||
: x1(_x1), y1(_y1), x2(_x2), y2(_y2), pxon(_pxon), pxoff(_pxoff), color(_color), alpha(_alpha), mode(_mode), aa(_aa) {}
|
||||
};
|
||||
|
||||
struct LICE_Ext_GetPixel_acceldata
|
||||
{
|
||||
int x, y;
|
||||
LICE_pixel px; // return
|
||||
|
||||
LICE_Ext_GetPixel_acceldata(int _x, int _y)
|
||||
: x(_x), y(_y), px(0) {}
|
||||
};
|
||||
|
||||
struct LICE_Ext_PutPixel_acceldata
|
||||
{
|
||||
int x, y;
|
||||
LICE_pixel color;
|
||||
float alpha;
|
||||
int mode;
|
||||
|
||||
LICE_Ext_PutPixel_acceldata(int _x, int _y, LICE_pixel _color, float _alpha, int _mode)
|
||||
: x(_x), y(_y), color(_color), alpha(_alpha), mode(_mode) {}
|
||||
};
|
||||
|
||||
struct LICE_Ext_SetClip_data
|
||||
{
|
||||
int x, y, w, h;
|
||||
|
||||
LICE_Ext_SetClip_data(int _x, int _y, int _w, int _h)
|
||||
: x(_x), y(_y), w(_w), h(_h) {}
|
||||
};
|
||||
|
||||
class pl_Mat;
|
||||
|
||||
struct LICE_Ext_DrawTriangle_acceldata
|
||||
{
|
||||
pl_Mat *mat; // will need to include plush.h to access this
|
||||
double VertexShades[3][3]; // for solid element
|
||||
float scrx[3], scry[3], scrz[3]; // scrz = 1/Zdist
|
||||
double mapping_coords[2][3][2]; // [texture or texture2][vertex][uv]
|
||||
};
|
||||
|
||||
struct LICE_Ext_WindowBlit_data
|
||||
{
|
||||
HWND hwnd;
|
||||
int destx, desty, srcx, srcy, w, h;
|
||||
|
||||
LICE_Ext_WindowBlit_data(HWND _hwnd, int _destx, int _desty, int _srcx, int _srcy, int _w, int _h)
|
||||
: hwnd(_hwnd), destx(_destx), desty(_desty), srcx(_srcx), srcy(_srcy), w(_w), h(_h) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
462
oversampling/WDL/lice/lice_gif.cpp
Normal file
462
oversampling/WDL/lice/lice_gif.cpp
Normal file
@@ -0,0 +1,462 @@
|
||||
/*
|
||||
Cockos WDL - LICE - Lightweight Image Compositing Engine
|
||||
Copyright (C) 2007 and later, Cockos Incorporated
|
||||
File: lice_gif.cpp (GIF loading for LICE)
|
||||
See lice.h for license and other information
|
||||
*/
|
||||
|
||||
#include "lice.h"
|
||||
#include "../heapbuf.h"
|
||||
#include "../fileread.h"
|
||||
#include <stdio.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
#include "../giflib/gif_lib.h"
|
||||
int _GifError;
|
||||
};
|
||||
|
||||
static void applyGifFrameToBitmap(LICE_IBitmap *bmp, GifFileType *fp, int transparent_pix, bool clear)
|
||||
{
|
||||
const int width=fp->Image.Width,height=fp->Image.Height;
|
||||
|
||||
LICE_pixel cmap[256];
|
||||
GifPixelType _linebuf[2048];
|
||||
GifPixelType *linebuf=width > 2048 ? (GifPixelType*)malloc(width*sizeof(GifPixelType)) : _linebuf;
|
||||
int y;
|
||||
|
||||
if (bmp)
|
||||
{
|
||||
y=0;
|
||||
if (fp->Image.ColorMap && fp->Image.ColorMap->Colors) for (;y<256 && y < fp->Image.ColorMap->ColorCount;y++)
|
||||
{
|
||||
GifColorType *ct=fp->Image.ColorMap->Colors+y;
|
||||
cmap[y]=LICE_RGBA(ct->Red,ct->Green,ct->Blue,255);
|
||||
}
|
||||
|
||||
if (fp->SColorMap && fp->SColorMap->Colors) for (;y<256 && y < fp->SColorMap->ColorCount;y++)
|
||||
{
|
||||
GifColorType *ct=fp->SColorMap->Colors+y;
|
||||
cmap[y]=LICE_RGBA(ct->Red,ct->Green,ct->Blue,255);
|
||||
}
|
||||
for (;y<256;y++) cmap[y]=0;
|
||||
|
||||
if (clear)
|
||||
{
|
||||
LICE_pixel col = 0;
|
||||
|
||||
if (fp->SColorMap && fp->SColorMap->Colors && fp->SBackGroundColor >= 0 && fp->SBackGroundColor < fp->SColorMap->ColorCount)
|
||||
{
|
||||
GifColorType *ct=fp->SColorMap->Colors+fp->SBackGroundColor;
|
||||
col = LICE_RGBA(ct->Red,ct->Green,ct->Blue,0);
|
||||
}
|
||||
else if (fp->SBackGroundColor>=0 && fp->SBackGroundColor<256)
|
||||
{
|
||||
col = cmap[fp->SBackGroundColor] & LICE_RGBA(255,255,255,0);
|
||||
}
|
||||
LICE_Clear(bmp,col);
|
||||
}
|
||||
}
|
||||
|
||||
const int bmp_h = bmp ? bmp->getHeight() : 0;
|
||||
const int bmp_w = bmp ? bmp->getWidth() : 0;
|
||||
LICE_pixel *bmp_ptr = bmp ? bmp->getBits() : NULL;
|
||||
int bmp_span = bmp ? bmp->getRowSpan() : 0;
|
||||
if (bmp && bmp->isFlipped() )
|
||||
{
|
||||
bmp_ptr += (bmp_h-1)*bmp_span;
|
||||
bmp_span = -bmp_span;
|
||||
}
|
||||
const int xpos = fp->Image.Left;
|
||||
|
||||
int skip=0;
|
||||
int use_width = width;
|
||||
if (xpos < 0) skip = -xpos;
|
||||
|
||||
if (use_width > bmp_w - xpos) use_width = bmp_w - xpos;
|
||||
|
||||
int ystate = 0, ypass=0;
|
||||
for (y=0; y < height; y ++)
|
||||
{
|
||||
if (DGifGetLine(fp,linebuf,width)==GIF_ERROR) break;
|
||||
|
||||
int ypos;
|
||||
if (fp->Image.Interlace)
|
||||
{
|
||||
if (ypass == 0)
|
||||
{
|
||||
ypos = ystate++ * 8;
|
||||
if (ypos >= height) { ypass++; ystate=0; }
|
||||
}
|
||||
if (ypass == 1)
|
||||
{
|
||||
ypos = ystate++ * 8 + 4;
|
||||
if (ypos >= height) { ypass++; ystate=0; }
|
||||
}
|
||||
if (ypass == 2)
|
||||
{
|
||||
ypos = ystate++ * 4 + 2;
|
||||
if (ypos >= height) { ypass++; ystate=0; }
|
||||
}
|
||||
if (ypass==3) ypos = ystate++ * 2 + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ypos = ystate++;
|
||||
}
|
||||
|
||||
ypos += fp->Image.Top;
|
||||
if (ypos < 0 || ypos >= bmp_h) continue;
|
||||
|
||||
LICE_pixel *p = bmp_ptr + ypos*bmp_span + xpos;
|
||||
int x;
|
||||
for (x = skip; x < use_width; x ++)
|
||||
{
|
||||
const int a = (int) linebuf[x];
|
||||
if (a != transparent_pix) p[x]=cmap[a];
|
||||
}
|
||||
}
|
||||
if (linebuf != _linebuf) free(linebuf);
|
||||
}
|
||||
|
||||
static int readfunc_fh(GifFileType *fh, GifByteType *buf, int sz)
|
||||
{
|
||||
return ((WDL_FileRead*)fh->UserData)->Read(buf,sz);
|
||||
}
|
||||
|
||||
|
||||
LICE_IBitmap *LICE_LoadGIF(const char *filename, LICE_IBitmap *bmp, int *nframes)
|
||||
{
|
||||
WDL_FileRead fpp(filename,0,65536);
|
||||
|
||||
if (nframes) *nframes=0;
|
||||
|
||||
if (!fpp.IsOpen()) return 0;
|
||||
|
||||
GifFileType *fp=DGifOpen(&fpp, readfunc_fh);
|
||||
if (!fp) return 0;
|
||||
|
||||
int transparent_pix = -1;
|
||||
|
||||
bool had_image = false;
|
||||
bool had_delay = false;
|
||||
bool need_new_frame = false;
|
||||
|
||||
const bool own_bmp = !bmp;
|
||||
GifRecordType RecordType;
|
||||
GifByteType *Extension;
|
||||
int ExtCode;
|
||||
LICE_WrapperBitmap workbm(NULL,0,0,0,false);
|
||||
WDL_HeapBuf workbuf(128*1024);
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
if (DGifGetRecordType(fp, &RecordType) == GIF_ERROR) break;
|
||||
|
||||
switch (RecordType)
|
||||
{
|
||||
case IMAGE_DESC_RECORD_TYPE:
|
||||
if (DGifGetImageDesc(fp) == GIF_ERROR)
|
||||
{
|
||||
RecordType = TERMINATE_RECORD_TYPE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!bmp) bmp=new WDL_NEW LICE_MemBitmap;
|
||||
|
||||
if (!had_image || (nframes && need_new_frame))
|
||||
{
|
||||
if (had_image)
|
||||
{
|
||||
// implies nframes
|
||||
const int ht = (*nframes+1) * (int)fp->SHeight;
|
||||
workbm.m_h = ht;
|
||||
workbm.m_w = (int)fp->SWidth;
|
||||
workbm.m_span = (workbm.m_w+3)&~3;
|
||||
workbm.m_buf = (LICE_pixel *) workbuf.ResizeOK(ht * sizeof(LICE_pixel) * workbm.m_span);
|
||||
if (!workbm.m_buf)
|
||||
{
|
||||
RecordType = TERMINATE_RECORD_TYPE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bmp) bmp->resize(fp->SWidth,fp->SHeight);
|
||||
|
||||
if (!bmp || bmp->getWidth() != (int)fp->SWidth || bmp->getHeight() != (int)fp->SHeight)
|
||||
{
|
||||
RecordType = TERMINATE_RECORD_TYPE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nframes)
|
||||
{
|
||||
if (*nframes > 0)
|
||||
{
|
||||
if (*nframes == 1)
|
||||
LICE_Blit(&workbm,bmp,0,0,0,0,bmp->getWidth(),bmp->getHeight(),1.0,LICE_BLIT_MODE_COPY);
|
||||
|
||||
LICE_Blit(&workbm,&workbm,0,workbm.getHeight()-(int)fp->SHeight,0,
|
||||
workbm.getHeight()-(int)fp->SHeight*2, workbm.getWidth(), (int)fp->SHeight,1.0f,LICE_BLIT_MODE_COPY);
|
||||
}
|
||||
|
||||
*nframes += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (nframes)
|
||||
{
|
||||
LICE_SubBitmap tmp(&workbm, 0,workbm.getHeight() - (int) fp->SHeight, workbm.getWidth(), (int)fp->SHeight);
|
||||
applyGifFrameToBitmap(&tmp,fp,transparent_pix,!had_image);
|
||||
}
|
||||
else
|
||||
applyGifFrameToBitmap(bmp,fp,transparent_pix,!had_image);
|
||||
|
||||
had_image = true;
|
||||
|
||||
need_new_frame = false;
|
||||
transparent_pix = -1;
|
||||
|
||||
if (had_delay)
|
||||
{
|
||||
if (!nframes)
|
||||
{
|
||||
RecordType = TERMINATE_RECORD_TYPE; // finish up if first frame is finished
|
||||
}
|
||||
else
|
||||
{
|
||||
need_new_frame = true;
|
||||
}
|
||||
had_delay = false;
|
||||
}
|
||||
break;
|
||||
case EXTENSION_RECORD_TYPE:
|
||||
if (DGifGetExtension(fp, &ExtCode, &Extension) == GIF_ERROR)
|
||||
{
|
||||
RecordType = TERMINATE_RECORD_TYPE;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (Extension != NULL)
|
||||
{
|
||||
if (ExtCode == 0xF9 && *Extension >= 4)
|
||||
{
|
||||
transparent_pix = -1;
|
||||
if (Extension[1]&1)
|
||||
{
|
||||
transparent_pix = Extension[4];
|
||||
}
|
||||
if (Extension[2] || Extension[3]) had_delay=true;
|
||||
}
|
||||
|
||||
if (DGifGetExtensionNext(fp, &Extension) == GIF_ERROR)
|
||||
{
|
||||
RecordType = TERMINATE_RECORD_TYPE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TERMINATE_RECORD_TYPE:
|
||||
break;
|
||||
default: /* Should be traps by DGifGetRecordType. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (RecordType != TERMINATE_RECORD_TYPE);
|
||||
|
||||
DGifCloseFile(fp);
|
||||
|
||||
if (had_image)
|
||||
{
|
||||
if (workbm.getWidth()) LICE_Copy(bmp,&workbm);
|
||||
return bmp;
|
||||
}
|
||||
|
||||
if (own_bmp) delete bmp;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class LICE_GIFLoader
|
||||
{
|
||||
public:
|
||||
_LICE_ImageLoader_rec rec;
|
||||
LICE_GIFLoader()
|
||||
{
|
||||
rec.loadfunc = loadfunc;
|
||||
rec.get_extlist = get_extlist;
|
||||
rec._next = LICE_ImageLoader_list;
|
||||
LICE_ImageLoader_list = &rec;
|
||||
}
|
||||
|
||||
static LICE_IBitmap *loadfunc(const char *filename, bool checkFileName, LICE_IBitmap *bmpbase)
|
||||
{
|
||||
if (checkFileName)
|
||||
{
|
||||
const char *p=filename;
|
||||
while (*p)p++;
|
||||
while (p>filename && *p != '\\' && *p != '/' && *p != '.') p--;
|
||||
if (stricmp(p,".gif")) return 0;
|
||||
}
|
||||
return LICE_LoadGIF(filename,bmpbase,NULL);
|
||||
}
|
||||
static const char *get_extlist()
|
||||
{
|
||||
return "GIF files (*.GIF)\0*.GIF\0";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
LICE_GIFLoader LICE_gifldr;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct lice_gif_read_ctx
|
||||
{
|
||||
WDL_FileRead *fh;
|
||||
GifFileType *gif;
|
||||
int msecpos;
|
||||
int state;
|
||||
WDL_FILEREAD_POSTYPE ipos;
|
||||
};
|
||||
|
||||
|
||||
void *LICE_GIF_LoadEx(const char *filename)
|
||||
{
|
||||
WDL_FileRead *fpp = new WDL_FileRead(filename,0,32768);
|
||||
|
||||
if (!fpp->IsOpen())
|
||||
{
|
||||
delete fpp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
GifFileType *gif=DGifOpen(fpp, readfunc_fh);
|
||||
if (!gif)
|
||||
{
|
||||
delete fpp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
lice_gif_read_ctx *ret = (lice_gif_read_ctx*)calloc(sizeof(lice_gif_read_ctx), 1);
|
||||
if (!ret)
|
||||
{
|
||||
DGifCloseFile(gif);
|
||||
delete fpp;
|
||||
return NULL;
|
||||
}
|
||||
ret->fh = fpp;
|
||||
ret->gif = gif;
|
||||
ret->msecpos = 0;
|
||||
ret->state = 0;
|
||||
ret->ipos = fpp->GetPosition();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void LICE_GIF_Close(void *handle)
|
||||
{
|
||||
lice_gif_read_ctx *h = (lice_gif_read_ctx*)handle;
|
||||
if (h)
|
||||
{
|
||||
DGifCloseFile(h->gif);
|
||||
delete h->fh;
|
||||
free(h);
|
||||
}
|
||||
}
|
||||
void LICE_GIF_Rewind(void *handle)
|
||||
{
|
||||
lice_gif_read_ctx *h = (lice_gif_read_ctx*)handle;
|
||||
if (h)
|
||||
{
|
||||
h->state = 0;
|
||||
h->msecpos = 0;
|
||||
h->fh->SetPosition(h->ipos);
|
||||
// todo: flush giflib too
|
||||
}
|
||||
}
|
||||
unsigned int LICE_GIF_GetFilePos(void *handle)
|
||||
{
|
||||
// only used for accounting at the moment, so meh
|
||||
lice_gif_read_ctx *h = (lice_gif_read_ctx*)handle;
|
||||
if (h && h->fh)
|
||||
{
|
||||
return (unsigned int) h->fh->GetPosition();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LICE_GIF_UpdateFrame(void *handle, LICE_IBitmap *bm)
|
||||
{
|
||||
lice_gif_read_ctx *h = (lice_gif_read_ctx*)handle;
|
||||
if (!h||h->state<0) return -2;
|
||||
GifFileType *fp = h->gif;
|
||||
|
||||
if (bm)
|
||||
{
|
||||
bm->resize(fp->SWidth, fp->SHeight);
|
||||
if (bm->getWidth() != (int)fp->SWidth || bm->getHeight() != (int)fp->SHeight) return -3;
|
||||
}
|
||||
|
||||
int has_delay = 0;
|
||||
int transparent_pix = -1;
|
||||
GifRecordType RecordType;
|
||||
GifByteType *Extension;
|
||||
int ExtCode;
|
||||
do
|
||||
{
|
||||
if (DGifGetRecordType(fp, &RecordType) == GIF_ERROR) return h->state = -5;
|
||||
switch (RecordType)
|
||||
{
|
||||
case IMAGE_DESC_RECORD_TYPE:
|
||||
if (DGifGetImageDesc(fp) == GIF_ERROR) return h->state = -4;
|
||||
|
||||
applyGifFrameToBitmap(bm,fp,transparent_pix,!h->state);
|
||||
h->state += 1;
|
||||
h->msecpos += has_delay*10;
|
||||
return has_delay*10;
|
||||
|
||||
case EXTENSION_RECORD_TYPE:
|
||||
if (DGifGetExtension(fp, &ExtCode, &Extension) == GIF_ERROR)
|
||||
{
|
||||
return h->state = -9;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (Extension != NULL)
|
||||
{
|
||||
if (ExtCode == 0xF9 && *Extension >= 4)
|
||||
{
|
||||
transparent_pix = -1;
|
||||
if (Extension[1]&1)
|
||||
{
|
||||
transparent_pix = Extension[4];
|
||||
}
|
||||
has_delay = ((int)Extension[3] << 8) + Extension[2];
|
||||
if (has_delay == 1) has_delay = 10; // https://www.biphelps.com/blog/The-Fastest-GIF-Does-Not-Exist
|
||||
}
|
||||
|
||||
if (DGifGetExtensionNext(fp, &Extension) == GIF_ERROR) return h->state = -8;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TERMINATE_RECORD_TYPE:
|
||||
break;
|
||||
default: /* Should be traps by DGifGetRecordType. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (RecordType != TERMINATE_RECORD_TYPE);
|
||||
|
||||
return h->state = -10;
|
||||
}
|
||||
|
||||
491
oversampling/WDL/lice/lice_gif_write.cpp
Normal file
491
oversampling/WDL/lice/lice_gif_write.cpp
Normal file
@@ -0,0 +1,491 @@
|
||||
/*
|
||||
Cockos WDL - LICE - Lightweight Image Compositing Engine
|
||||
Copyright (C) 2007 and later, Cockos Incorporated
|
||||
File: lice_gif.cpp (GIF loading for LICE)
|
||||
See lice.h for license and other information
|
||||
*/
|
||||
|
||||
#include "lice.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../wdltypes.h"
|
||||
#include "../filewrite.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
#include "../giflib/gif_lib.h"
|
||||
//int _GifError;
|
||||
};
|
||||
|
||||
|
||||
struct liceGifWriteRec
|
||||
{
|
||||
GifFileType *f;
|
||||
WDL_FileWrite *fh;
|
||||
ColorMapObject *cmap;
|
||||
GifPixelType *linebuf;
|
||||
LICE_IBitmap *prevframe; // used when multiframe, transalpha<0
|
||||
void *last_octree;
|
||||
LICE_pixel last_palette[256];
|
||||
unsigned char from15to8bit[32][32][32];//r,g,b
|
||||
|
||||
int transalpha;
|
||||
int w,h;
|
||||
bool append;
|
||||
bool dither;
|
||||
bool has_had_frame;
|
||||
bool has_global_cmap;
|
||||
|
||||
bool has_from15to8bit; // set when last_octree has been generated into from15to8bit
|
||||
};
|
||||
|
||||
static inline GifPixelType QuantPixel(LICE_pixel p, liceGifWriteRec *wr)
|
||||
{
|
||||
return wr->from15to8bit[LICE_GETR(p)>>3][LICE_GETG(p)>>3][LICE_GETB(p)>>3];
|
||||
}
|
||||
|
||||
static int generate_palette_from_octree(void *ww, void *octree, int numcolors)
|
||||
{
|
||||
liceGifWriteRec *wr = (liceGifWriteRec *)ww;
|
||||
if (!octree||!ww||numcolors>256) return 0;
|
||||
|
||||
ColorMapObject *cmap = wr->cmap;
|
||||
|
||||
int palette_sz=0;
|
||||
|
||||
// store palette
|
||||
{
|
||||
LICE_pixel* palette=wr->last_palette;
|
||||
|
||||
palette_sz = LICE_ExtractOctreePalette(octree, palette);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < palette_sz; ++i)
|
||||
{
|
||||
cmap->Colors[i].Red = LICE_GETR(palette[i]);
|
||||
cmap->Colors[i].Green = LICE_GETG(palette[i]);
|
||||
cmap->Colors[i].Blue = LICE_GETB(palette[i]);
|
||||
}
|
||||
for (i = palette_sz; i < numcolors; ++i)
|
||||
{
|
||||
cmap->Colors[i].Red = cmap->Colors[i].Green = cmap->Colors[i].Blue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
wr->has_from15to8bit = false;
|
||||
wr->has_global_cmap=true;
|
||||
|
||||
return palette_sz;
|
||||
}
|
||||
|
||||
static void generate15to8(void *ww, void *octree)
|
||||
{
|
||||
liceGifWriteRec *wr = (liceGifWriteRec *)ww;
|
||||
if (!octree||!ww) return;
|
||||
|
||||
// map palette to 16 bit
|
||||
unsigned char r,g,b;
|
||||
for(r=0;r<32;r++)
|
||||
{
|
||||
unsigned char cr = r<<3;
|
||||
for (g=0;g<32;g++)
|
||||
{
|
||||
unsigned char cg = g<<3;
|
||||
for (b=0;b<32;b++)
|
||||
{
|
||||
unsigned char cb = b<<3;
|
||||
LICE_pixel col = LICE_RGBA(cr,cg,cb,0);
|
||||
wr->from15to8bit[r][g][b] = LICE_FindInOctree(octree, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
wr->has_from15to8bit=true;
|
||||
}
|
||||
|
||||
int LICE_SetGIFColorMapFromOctree(void *ww, void *octree, int numcolors)
|
||||
{
|
||||
const int rv = generate_palette_from_octree(ww,octree,numcolors);
|
||||
generate15to8(ww,octree);
|
||||
return rv;
|
||||
}
|
||||
|
||||
unsigned int LICE_WriteGIFGetSize(void *handle)
|
||||
{
|
||||
if (handle)
|
||||
{
|
||||
liceGifWriteRec *wr = (liceGifWriteRec*)handle;
|
||||
if (wr->fh) return (unsigned int) ((WDL_FileWrite *)wr->fh)->GetPosition();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool LICE_WriteGIFFrame(void *handle, LICE_IBitmap *frame, int xpos, int ypos, bool perImageColorMap, int frame_delay, int nreps)
|
||||
{
|
||||
liceGifWriteRec *wr = (liceGifWriteRec*)handle;
|
||||
if (!wr) return false;
|
||||
|
||||
bool isFirst=false;
|
||||
if (!wr->has_had_frame)
|
||||
{
|
||||
wr->has_had_frame=true;
|
||||
isFirst=true;
|
||||
|
||||
if (!perImageColorMap && !wr->has_global_cmap)
|
||||
{
|
||||
const int ccnt = 256 - (wr->transalpha?1:0);
|
||||
void* octree = wr->last_octree;
|
||||
if (!octree) wr->last_octree = octree = LICE_CreateOctree(ccnt);
|
||||
else LICE_ResetOctree(octree,ccnt);
|
||||
|
||||
if (octree)
|
||||
{
|
||||
LICE_BuildOctree(octree, frame);
|
||||
// sets has_global_cmap
|
||||
int pcnt = generate_palette_from_octree(wr, octree, ccnt);
|
||||
|
||||
if (pcnt < 256 && wr->transalpha) pcnt++;
|
||||
int nb = 1;
|
||||
while (nb < 8 && (1<<nb) < pcnt) nb++;
|
||||
wr->cmap->ColorCount = 1<<nb;
|
||||
wr->cmap->BitsPerPixel=nb;
|
||||
}
|
||||
}
|
||||
|
||||
if (!wr->append) EGifPutScreenDesc(wr->f,wr->w,wr->h,8,0,wr->has_global_cmap ? wr->cmap : 0);
|
||||
|
||||
}
|
||||
|
||||
int usew=frame->getWidth(), useh=frame->getHeight();
|
||||
if (xpos+usew > wr->w) usew = wr->w-xpos;
|
||||
if (ypos+useh > wr->h) useh = wr->h-ypos;
|
||||
if (usew<1||useh<1) return false;
|
||||
|
||||
int pixcnt=usew*useh;
|
||||
|
||||
const int trans_chan_mask = wr->transalpha&0xff; // -1 means 0xff by default, user can change this accordingly
|
||||
const LICE_pixel trans_mask = LICE_RGBA(trans_chan_mask,trans_chan_mask,trans_chan_mask,0);
|
||||
const bool advanced_trans_stats = !!(wr->transalpha&0x100);
|
||||
|
||||
if (perImageColorMap && !wr->has_global_cmap)
|
||||
{
|
||||
const int ccnt = 256 - (wr->transalpha?1:0);
|
||||
void* octree = wr->last_octree;
|
||||
if (!octree) wr->last_octree = octree = LICE_CreateOctree(ccnt);
|
||||
else LICE_ResetOctree(octree,ccnt);
|
||||
if (octree)
|
||||
{
|
||||
if ((!isFirst || frame_delay) && wr->transalpha<0 && wr->prevframe)
|
||||
{
|
||||
LICE_SubBitmap tmpprev(wr->prevframe, xpos, ypos, usew, useh);
|
||||
int pc=LICE_BuildOctreeForDiff(octree,frame,&tmpprev,trans_mask);
|
||||
if (!advanced_trans_stats) pixcnt = pc;
|
||||
}
|
||||
else if (wr->transalpha>0)
|
||||
pixcnt=LICE_BuildOctreeForAlpha(octree, frame,wr->transalpha&0xff);
|
||||
else
|
||||
LICE_BuildOctree(octree, frame);
|
||||
|
||||
// sets has_global_cmap (clear below)
|
||||
int pcnt = generate_palette_from_octree(wr, octree, ccnt);
|
||||
|
||||
wr->has_global_cmap=false;
|
||||
if (pcnt < 256 && wr->transalpha) pcnt++;
|
||||
int nb = 1;
|
||||
while (nb < 8 && (1<<nb) < pcnt) nb++;
|
||||
wr->cmap->ColorCount = 1<<nb;
|
||||
wr->cmap->BitsPerPixel=nb;
|
||||
}
|
||||
}
|
||||
|
||||
if (!wr->has_from15to8bit && pixcnt > 40000 && wr->last_octree)
|
||||
{
|
||||
generate15to8(wr,wr->last_octree);
|
||||
}
|
||||
|
||||
const unsigned char transparent_pix = wr->cmap->ColorCount-1;
|
||||
unsigned char gce[4] = { 0, };
|
||||
if (wr->transalpha)
|
||||
{
|
||||
gce[0] |= 1;
|
||||
gce[3] = transparent_pix;
|
||||
}
|
||||
|
||||
int a = frame_delay/10;
|
||||
if(a<2&&frame_delay)a=2; // https://www.biphelps.com/blog/The-Fastest-GIF-Does-Not-Exist
|
||||
else if (a>60000) a=60000;
|
||||
gce[1]=(a)&255;
|
||||
gce[2]=(a)>>8;
|
||||
|
||||
if (isFirst && frame_delay && nreps!=1 && !wr->append)
|
||||
{
|
||||
int nr = nreps > 1 && nreps <= 65536 ? nreps-1 : 0;
|
||||
unsigned char ext[]={0xB, 'N','E','T','S','C','A','P','E','2','.','0',3,1,(unsigned char) (nr&0xff), (unsigned char) ((nr>>8)&0xff)};
|
||||
EGifPutExtension(wr->f,0xFF, sizeof(ext),ext);
|
||||
}
|
||||
|
||||
if (gce[0]||gce[1]||gce[2])
|
||||
EGifPutExtension(wr->f, 0xF9, sizeof(gce), gce);
|
||||
|
||||
|
||||
EGifPutImageDesc(wr->f, xpos, ypos, usew,useh, 0, wr->has_global_cmap ? NULL : wr->cmap);
|
||||
|
||||
GifPixelType *linebuf = wr->linebuf;
|
||||
int y;
|
||||
|
||||
void *use_octree = wr->has_from15to8bit ? NULL : wr->last_octree;
|
||||
|
||||
if ((!isFirst || frame_delay) && wr->transalpha<0)
|
||||
{
|
||||
bool ignFr=false;
|
||||
if (!wr->prevframe)
|
||||
{
|
||||
ignFr=true;
|
||||
wr->prevframe = new WDL_NEW LICE_MemBitmap(wr->w,wr->h);
|
||||
LICE_Clear(wr->prevframe,0);
|
||||
}
|
||||
|
||||
LICE_SubBitmap tmp(wr->prevframe,xpos,ypos,usew,useh);
|
||||
|
||||
LICE_pixel last_pixel_rgb=0;
|
||||
GifPixelType last_pixel_idx=transparent_pix;
|
||||
|
||||
int pix_stats[256];
|
||||
if (advanced_trans_stats) memset(pix_stats,0,sizeof(pix_stats));
|
||||
pix_stats[transparent_pix] = -8;
|
||||
|
||||
for(y=0;y<useh;y++)
|
||||
{
|
||||
int rdy=y,rdy2=y;
|
||||
if (frame->isFlipped()) rdy = frame->getHeight()-1-y;
|
||||
if (tmp.isFlipped()) rdy2 = tmp.getHeight()-1-y;
|
||||
const LICE_pixel *in = frame->getBits() + rdy*frame->getRowSpan();
|
||||
const LICE_pixel *in2 = tmp.getBits() + rdy2*tmp.getRowSpan();
|
||||
int x;
|
||||
|
||||
if (advanced_trans_stats)
|
||||
{
|
||||
if (use_octree) for(x=0;x<usew;x++)
|
||||
{
|
||||
const LICE_pixel p = in[x]&trans_mask;
|
||||
if (last_pixel_idx == transparent_pix || last_pixel_rgb!=p)
|
||||
{
|
||||
if (ignFr || p != (in2[x]&trans_mask)) last_pixel_idx = LICE_FindInOctree(use_octree,p);
|
||||
else
|
||||
{
|
||||
const GifPixelType np = LICE_FindInOctree(use_octree,p);
|
||||
if (p != (wr->last_palette[np]&trans_mask) || pix_stats[transparent_pix] > pix_stats[np])
|
||||
last_pixel_idx = transparent_pix;
|
||||
else
|
||||
last_pixel_idx = np;
|
||||
}
|
||||
}
|
||||
linebuf[x] = last_pixel_idx;
|
||||
pix_stats[last_pixel_idx]++;
|
||||
last_pixel_rgb = p;
|
||||
}
|
||||
else for(x=0;x<usew;x++)
|
||||
{
|
||||
const LICE_pixel p = in[x]&trans_mask;
|
||||
if (last_pixel_idx == transparent_pix || last_pixel_rgb!=p)
|
||||
{
|
||||
if (ignFr || p != (in2[x]&trans_mask)) last_pixel_idx = QuantPixel(p,wr);
|
||||
else
|
||||
{
|
||||
const GifPixelType np = QuantPixel(p,wr);
|
||||
|
||||
if (p != (wr->last_palette[np]&trans_mask) || pix_stats[transparent_pix] > pix_stats[np])
|
||||
last_pixel_idx = transparent_pix;
|
||||
else
|
||||
last_pixel_idx = np;
|
||||
}
|
||||
}
|
||||
linebuf[x] = last_pixel_idx;
|
||||
pix_stats[last_pixel_idx]++;
|
||||
last_pixel_rgb = p;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// optimize solids by reusing the same value if previous rgb was the same, also avoid switching between
|
||||
// from color to transparent if the color hasn't changed
|
||||
if (use_octree) for(x=0;x<usew;x++)
|
||||
{
|
||||
const LICE_pixel p = in[x]&trans_mask;
|
||||
if (last_pixel_idx == transparent_pix || last_pixel_rgb!=p)
|
||||
{
|
||||
if (ignFr || p != (in2[x]&trans_mask)) last_pixel_idx = LICE_FindInOctree(use_octree,last_pixel_rgb = p);
|
||||
else last_pixel_idx = transparent_pix;
|
||||
}
|
||||
linebuf[x] = last_pixel_idx;
|
||||
}
|
||||
else for(x=0;x<usew;x++)
|
||||
{
|
||||
const LICE_pixel p = in[x]&trans_mask;
|
||||
if (last_pixel_idx == transparent_pix || last_pixel_rgb!=p)
|
||||
{
|
||||
if (ignFr || p != (in2[x]&trans_mask)) last_pixel_idx = QuantPixel(last_pixel_rgb = p,wr);
|
||||
else last_pixel_idx = transparent_pix;
|
||||
}
|
||||
linebuf[x] = last_pixel_idx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EGifPutLine(wr->f, linebuf, usew);
|
||||
}
|
||||
|
||||
LICE_Blit(&tmp,frame,0,0,0,0,usew,useh,1.0f,LICE_BLIT_MODE_COPY);
|
||||
|
||||
}
|
||||
else if (wr->transalpha>0)
|
||||
{
|
||||
const unsigned int al = wr->transalpha&0xff;
|
||||
for(y=0;y<useh;y++)
|
||||
{
|
||||
int rdy=y;
|
||||
if (frame->isFlipped()) rdy = frame->getHeight()-1-y;
|
||||
const LICE_pixel *in = frame->getBits() + rdy*frame->getRowSpan();
|
||||
int x;
|
||||
if (use_octree) for(x=0;x<usew;x++)
|
||||
{
|
||||
const LICE_pixel p = in[x];
|
||||
if (LICE_GETA(p)<al) linebuf[x]=transparent_pix;
|
||||
else linebuf[x] = LICE_FindInOctree(use_octree,p);
|
||||
}
|
||||
else for(x=0;x<usew;x++)
|
||||
{
|
||||
const LICE_pixel p = in[x];
|
||||
if (LICE_GETA(p)<al) linebuf[x]=transparent_pix;
|
||||
else linebuf[x] = QuantPixel(p,wr);
|
||||
}
|
||||
EGifPutLine(wr->f, linebuf, usew);
|
||||
}
|
||||
}
|
||||
else for(y=0;y<useh;y++)
|
||||
{
|
||||
int rdy=y;
|
||||
if (frame->isFlipped()) rdy = frame->getHeight()-1-y;
|
||||
const LICE_pixel *in = frame->getBits() + rdy*frame->getRowSpan();
|
||||
int x;
|
||||
if (use_octree) for(x=0;x<usew;x++) linebuf[x] = LICE_FindInOctree(use_octree,in[x]);
|
||||
else for(x=0;x<usew;x++) linebuf[x] = QuantPixel(in[x],wr);
|
||||
EGifPutLine(wr->f, linebuf, usew);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int writefunc_fh(GifFileType *fh, const GifByteType *buf, int sz)
|
||||
{
|
||||
return ((WDL_FileWrite *)fh->UserData)->Write(buf,sz);
|
||||
}
|
||||
|
||||
void *LICE_WriteGIFBeginNoFrame(const char *filename, int w, int h, int transparent_alpha, bool dither, bool is_append)
|
||||
{
|
||||
WDL_FileWrite *fp = new WDL_FileWrite(filename,1,65536,16,16,is_append);
|
||||
if (!fp->IsOpen())
|
||||
{
|
||||
delete fp;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
EGifSetGifVersion("89a");
|
||||
|
||||
|
||||
GifFileType *f = EGifOpen(fp,writefunc_fh);
|
||||
if (!f)
|
||||
{
|
||||
delete fp;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
liceGifWriteRec *wr = (liceGifWriteRec*)calloc(sizeof(liceGifWriteRec),1);
|
||||
wr->f = f;
|
||||
wr->fh = fp;
|
||||
wr->append = is_append;
|
||||
wr->dither = dither;
|
||||
wr->w=w;
|
||||
wr->h=h;
|
||||
wr->cmap = (ColorMapObject*)calloc(sizeof(ColorMapObject)+256*sizeof(GifColorType),1);
|
||||
wr->cmap->Colors = (GifColorType*)(wr->cmap+1);
|
||||
wr->cmap->ColorCount=256;
|
||||
wr->cmap->BitsPerPixel=8;
|
||||
wr->has_had_frame=false;
|
||||
wr->has_global_cmap=false;
|
||||
wr->has_from15to8bit=false;
|
||||
wr->last_octree=NULL;
|
||||
|
||||
wr->linebuf = (GifPixelType*)malloc(wr->w*sizeof(GifPixelType));
|
||||
wr->transalpha = transparent_alpha;
|
||||
|
||||
return wr;
|
||||
}
|
||||
void *LICE_WriteGIFBegin(const char *filename, LICE_IBitmap *firstframe, int transparent_alpha, int frame_delay, bool dither, int nreps)
|
||||
{
|
||||
if (!firstframe) return NULL;
|
||||
|
||||
void *wr=LICE_WriteGIFBeginNoFrame(filename,firstframe->getWidth(),firstframe->getHeight(),transparent_alpha,dither);
|
||||
if (wr) LICE_WriteGIFFrame(wr,firstframe,0,0,true,frame_delay,nreps);
|
||||
|
||||
return wr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool LICE_WriteGIFEnd(void *handle)
|
||||
{
|
||||
liceGifWriteRec *wr = (liceGifWriteRec*)handle;
|
||||
if (!wr) return false;
|
||||
|
||||
int ret = EGifCloseFile(wr->f);
|
||||
|
||||
free(wr->linebuf);
|
||||
free(wr->cmap);
|
||||
if (wr->last_octree) LICE_DestroyOctree(wr->last_octree);
|
||||
|
||||
delete wr->prevframe;
|
||||
delete wr->fh;
|
||||
|
||||
free(wr);
|
||||
|
||||
return ret!=GIF_ERROR;
|
||||
}
|
||||
|
||||
|
||||
bool LICE_WriteGIF(const char *filename, LICE_IBitmap *bmp, int transparent_alpha, bool dither)
|
||||
{
|
||||
// todo: alpha?
|
||||
if (!bmp) return false;
|
||||
|
||||
int has_transparent = 0;
|
||||
if (transparent_alpha>0)
|
||||
{
|
||||
int y=bmp->getHeight();
|
||||
LICE_pixel *p = bmp->getBits();
|
||||
int w = bmp->getWidth();
|
||||
while (y--&&!has_transparent)
|
||||
{
|
||||
int x=w;
|
||||
while(x--)
|
||||
{
|
||||
if (LICE_GETA(*p) < (unsigned int)transparent_alpha)
|
||||
{
|
||||
has_transparent=1;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
p+=bmp->getRowSpan()-w;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void *wr=LICE_WriteGIFBeginNoFrame(filename,bmp->getWidth(),bmp->getHeight(),has_transparent?transparent_alpha:0,dither);
|
||||
if (!wr) return false;
|
||||
|
||||
LICE_WriteGIFFrame(wr,bmp,0,0,false,0);
|
||||
|
||||
return LICE_WriteGIFEnd(wr);
|
||||
}
|
||||
264
oversampling/WDL/lice/lice_gl_ctx.cpp
Normal file
264
oversampling/WDL/lice/lice_gl_ctx.cpp
Normal file
@@ -0,0 +1,264 @@
|
||||
#include "lice_gl_ctx.h"
|
||||
|
||||
#define MAX_CACHED_GLYPHS 4096
|
||||
|
||||
// create one hidden window per process to hold the openGL state,
|
||||
// its GL render context stays current for the life of the process,
|
||||
// we serve all framebuffers from the same render context
|
||||
|
||||
class LICE_GL_ctx
|
||||
{
|
||||
public:
|
||||
|
||||
LICE_GL_ctx();
|
||||
~LICE_GL_ctx();
|
||||
|
||||
bool IsValid();
|
||||
HWND GetWindow() { return m_hwnd; }
|
||||
void Close();
|
||||
|
||||
GLUnurbsObj* GetNurbsObj(int linetol=8); // linetol = maximum number of straight-line pixels
|
||||
|
||||
int GetTexFromGlyph(const unsigned char* glyph, int glyph_w, int glyph_h);
|
||||
void ClearTex();
|
||||
|
||||
struct GlyphCache
|
||||
{
|
||||
unsigned int tex;
|
||||
unsigned char* glyph; // lives on the heap
|
||||
int glyph_w, glyph_h;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
bool Init();
|
||||
|
||||
bool m_init_tried;
|
||||
HINSTANCE m_gldll;
|
||||
HWND m_hwnd;
|
||||
HGLRC m_glrc;
|
||||
|
||||
GLUnurbsObj* m_nurbs; // keep this here for easy reuse
|
||||
|
||||
GlyphCache m_glyphCache[MAX_CACHED_GLYPHS];
|
||||
int m_nCachedGlyphs;
|
||||
};
|
||||
|
||||
LICE_GL_ctx::LICE_GL_ctx()
|
||||
{
|
||||
m_init_tried = false;
|
||||
m_gldll = 0;
|
||||
m_hwnd = 0;
|
||||
m_glrc = 0;
|
||||
m_nurbs = 0;
|
||||
memset(m_glyphCache, 0, MAX_CACHED_GLYPHS*sizeof(GlyphCache));
|
||||
m_nCachedGlyphs = 0;
|
||||
}
|
||||
|
||||
LICE_GL_ctx::~LICE_GL_ctx()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
bool LICE_GL_ctx::Init()
|
||||
{
|
||||
m_init_tried = true;
|
||||
|
||||
m_gldll = LoadLibrary("opengl32.dll");
|
||||
if (!m_gldll)
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// create a minimal GL render context to serve FBOs out of
|
||||
WNDCLASS wc;
|
||||
memset(&wc, 0, sizeof(WNDCLASS));
|
||||
wc.hInstance = GetModuleHandle(0);
|
||||
wc.lpfnWndProc = DefWindowProc;
|
||||
wc.lpszClassName = "LICE_GL_ctx";
|
||||
RegisterClass(&wc);
|
||||
m_hwnd = CreateWindow("LICE_GL_ctx", "LICE_GL_ctx", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, GetModuleHandle(0), 0);
|
||||
HDC dc = GetDC(m_hwnd);
|
||||
if (!dc)
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
|
||||
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.cColorBits = 24;
|
||||
pfd.cAlphaBits = 8;
|
||||
int pxfmt = ChoosePixelFormat(dc, &pfd);
|
||||
if (!SetPixelFormat(dc, pxfmt, &pfd))
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_glrc = wglCreateContext(dc);
|
||||
if (!wglMakeCurrent(dc, m_glrc)) // render context should stay current throughout
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
char *rendstr = (char*) glGetString(GL_RENDERER);
|
||||
if (!rendstr || strstr(rendstr, "GDI"))
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// check now for all the extension functions we will ever need
|
||||
if (glewInit() != GLEW_OK ||
|
||||
!glewIsSupported("GL_EXT_framebuffer_object") ||
|
||||
!glewIsSupported("GL_ARB_texture_rectangle"))
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// any one-time initialization goes here
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
ReleaseDC(m_hwnd, dc);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LICE_GL_ctx::IsValid()
|
||||
{
|
||||
if (m_gldll && m_glrc) return true;
|
||||
if (!m_init_tried) return Init();
|
||||
return false;
|
||||
}
|
||||
|
||||
void LICE_GL_ctx::Close()
|
||||
{
|
||||
ClearTex();
|
||||
if (m_nurbs)
|
||||
{
|
||||
gluDeleteNurbsRenderer(m_nurbs);
|
||||
m_nurbs = 0;
|
||||
}
|
||||
if (m_glrc)
|
||||
{
|
||||
wglMakeCurrent(0, 0);
|
||||
wglDeleteContext(m_glrc);
|
||||
m_glrc = 0;
|
||||
}
|
||||
if (m_hwnd)
|
||||
{
|
||||
DestroyWindow(m_hwnd);
|
||||
m_hwnd = 0;
|
||||
}
|
||||
if (m_gldll)
|
||||
{
|
||||
FreeLibrary(m_gldll);
|
||||
m_gldll = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GLUnurbsObj* LICE_GL_ctx::GetNurbsObj(int linetol)
|
||||
{
|
||||
if (!IsValid()) return 0;
|
||||
if (!m_nurbs) m_nurbs = gluNewNurbsRenderer();
|
||||
if (m_nurbs) gluNurbsProperty(m_nurbs, GLU_SAMPLING_TOLERANCE, (float)linetol);
|
||||
return m_nurbs;
|
||||
}
|
||||
|
||||
void LICE_GL_ctx::ClearTex()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < m_nCachedGlyphs; ++i)
|
||||
{
|
||||
glDeleteTextures(1, &m_glyphCache[i].tex);
|
||||
free(m_glyphCache[i].glyph);
|
||||
memset(&m_glyphCache[i], 0, sizeof(GlyphCache));
|
||||
}
|
||||
m_nCachedGlyphs = 0;
|
||||
}
|
||||
|
||||
static int _glyphcmp(const void* p1, const void* p2)
|
||||
{
|
||||
LICE_GL_ctx::GlyphCache* gc1 = (LICE_GL_ctx::GlyphCache*) p1;
|
||||
LICE_GL_ctx::GlyphCache* gc2 = (LICE_GL_ctx::GlyphCache*) p2;
|
||||
|
||||
if (gc1->glyph_w < gc2->glyph_w) return -1;
|
||||
if (gc1->glyph_w > gc2->glyph_w) return 1;
|
||||
if (gc1->glyph_h < gc2->glyph_h) return -1;
|
||||
if (gc1->glyph_h > gc2->glyph_h) return 1;
|
||||
return memcmp(gc1->glyph, gc2->glyph, gc1->glyph_w*gc1->glyph_h);
|
||||
}
|
||||
|
||||
int LICE_GL_ctx::GetTexFromGlyph(const unsigned char* glyph, int glyph_w, int glyph_h)
|
||||
{
|
||||
if (!IsValid()) return false;
|
||||
|
||||
GlyphCache gc;
|
||||
gc.tex = 0;
|
||||
gc.glyph = (unsigned char *)glyph;
|
||||
gc.glyph_w = glyph_w;
|
||||
gc.glyph_h = glyph_h;
|
||||
|
||||
GlyphCache* p = (GlyphCache*) bsearch(&gc, m_glyphCache, m_nCachedGlyphs, sizeof(GlyphCache), _glyphcmp);
|
||||
if (p) return p->tex;
|
||||
|
||||
glGenTextures(1, &gc.tex);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, gc.tex);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_ALPHA8, glyph_w, glyph_h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, glyph);
|
||||
|
||||
if (m_nCachedGlyphs >= MAX_CACHED_GLYPHS) ClearTex(); // quick & dirty
|
||||
|
||||
gc.glyph = (unsigned char*) malloc(glyph_w*glyph_h);
|
||||
memcpy(gc.glyph, glyph, glyph_w*glyph_h);
|
||||
m_glyphCache[m_nCachedGlyphs++] = gc; // copy
|
||||
qsort(m_glyphCache, m_nCachedGlyphs, sizeof(GlyphCache), _glyphcmp);
|
||||
|
||||
return gc.tex;
|
||||
}
|
||||
|
||||
////////
|
||||
|
||||
static LICE_GL_ctx s_glctx; // one static opengl context object per process
|
||||
|
||||
|
||||
bool LICE_GL_IsValid()
|
||||
{
|
||||
return s_glctx.IsValid();
|
||||
}
|
||||
|
||||
HWND LICE_GL_GetWindow()
|
||||
{
|
||||
if (s_glctx.IsValid()) return s_glctx.GetWindow();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LICE_GL_CloseCtx()
|
||||
{
|
||||
s_glctx.Close();
|
||||
}
|
||||
|
||||
GLUnurbsObj* LICE_GL_GetNurbsObj(int linetol) // linetol = maximum number of straight-line pixels
|
||||
{
|
||||
return s_glctx.GetNurbsObj(linetol);
|
||||
}
|
||||
|
||||
GLuint LICE_GL_GetTexFromGlyph(const unsigned char* glyph, int glyph_w, int glyph_h)
|
||||
{
|
||||
return s_glctx.GetTexFromGlyph(glyph, glyph_w, glyph_h);
|
||||
}
|
||||
|
||||
void LICE_GL_ClearTex()
|
||||
{
|
||||
s_glctx.ClearTex();
|
||||
}
|
||||
|
||||
27
oversampling/WDL/lice/lice_gl_ctx.h
Normal file
27
oversampling/WDL/lice/lice_gl_ctx.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef _GL_CTX_
|
||||
#define _GL_CTX_
|
||||
|
||||
#include "lice.h"
|
||||
|
||||
#define GLEW_STATIC
|
||||
#include "glew/include/gl/glew.h"
|
||||
#include "glew/include/gl/wglew.h"
|
||||
#include "glew/include/gl/wglext.h"
|
||||
|
||||
// GL context functions
|
||||
// opening and managing GL context is handled behind the scenes
|
||||
|
||||
|
||||
bool LICE_GL_IsValid(); // GL context is initialized (will be lazy initialized on first call) and valid
|
||||
|
||||
HWND LICE_GL_GetWindow(); // Get the window that owns the GL context (one per process)
|
||||
|
||||
void LICE_GL_CloseCtx(); // Something failed, turn off GL context forever so we don't keep failing
|
||||
|
||||
GLUnurbsObj* LICE_GL_GetNurbsObj(int linetol=8); // linetol = maximum number of straight-line pixels
|
||||
|
||||
// facility for associating a glyph with a texture
|
||||
GLuint LICE_GL_GetTexFromGlyph(const unsigned char* glyph, int glyph_w, int glyph_h);
|
||||
void LICE_GL_ClearTex();
|
||||
|
||||
#endif
|
||||
708
oversampling/WDL/lice/lice_glbitmap.cpp
Normal file
708
oversampling/WDL/lice/lice_glbitmap.cpp
Normal file
@@ -0,0 +1,708 @@
|
||||
#include "lice_glbitmap.h"
|
||||
#include "lice_gl_ctx.h"
|
||||
|
||||
#include "../plush2/plush.h"
|
||||
|
||||
LICE_GLBitmap::LICE_GLBitmap()
|
||||
{
|
||||
m_bmp = 0;
|
||||
m_fbo = 0;
|
||||
m_tex = 0;
|
||||
m_bufloc = EMPTY;
|
||||
}
|
||||
|
||||
// This is separate from the constructor for initialization order reasons
|
||||
void LICE_GLBitmap::Init(LICE_IBitmap* bmp, int w, int h)
|
||||
{
|
||||
m_bmp = bmp;
|
||||
if (w > 0 && h > 0) CreateFBO(w, h);
|
||||
}
|
||||
|
||||
bool LICE_GLBitmap::CreateFBO(int w, int h)
|
||||
{
|
||||
if (LICE_GL_IsValid())
|
||||
{
|
||||
if (m_fbo) ReleaseFBO();
|
||||
glGenFramebuffersEXT(1, &m_fbo); // create a new empty FBO
|
||||
if (m_fbo)
|
||||
{
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); // bind this FBO so it is the rendering target
|
||||
glEnable(GL_TEXTURE_RECTANGLE_ARB); // enable texturing
|
||||
glGenTextures(1, &m_tex); // create a new texture to be the backing store
|
||||
if (m_tex)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_tex); // bind this texture so it is the texturing target
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // we won't be scaling it for this purpose
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // size the texture
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_tex, 0); // attach the texture as the backing store for the FBO
|
||||
}
|
||||
glDisable(GL_TEXTURE_RECTANGLE_ARB); // done texturing
|
||||
}
|
||||
|
||||
return BindFBO(); // this tests the FBO for validity
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
LICE_GL_SysBitmap::LICE_GL_SysBitmap(int w, int h)
|
||||
: m_sysbmp(w, h)
|
||||
{
|
||||
Init(&m_sysbmp, w, h);
|
||||
}
|
||||
|
||||
LICE_GL_MemBitmap::LICE_GL_MemBitmap(int w, int h)
|
||||
: m_membmp(w, h)
|
||||
{
|
||||
Init(&m_membmp, w, h);
|
||||
}
|
||||
|
||||
HDC LICE_GL_SysBitmap::getDC()
|
||||
{
|
||||
// no known way to get a DC directly from an offscreen openGL render context, sadly
|
||||
FramebufferFromGPU();
|
||||
OutputDebugString("GL to screen");
|
||||
return m_sysbmp.getDC();
|
||||
}
|
||||
|
||||
|
||||
LICE_GL_SubBitmap::LICE_GL_SubBitmap(LICE_IBitmap *parent, int x, int y, int w, int h)
|
||||
{
|
||||
m_parent = parent;
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
m_w = w;
|
||||
m_h = h;
|
||||
}
|
||||
|
||||
LICE_pixel* LICE_GL_SubBitmap::getBits()
|
||||
{
|
||||
if (!m_parent) return 0;
|
||||
return m_parent->getBits()+m_y*m_parent->getRowSpan()+m_x;
|
||||
}
|
||||
|
||||
bool LICE_GL_SubBitmap::resize(int w, int h)
|
||||
{
|
||||
if (w == m_w && h == m_h) return false;
|
||||
m_w = w;
|
||||
m_h = h;
|
||||
return true;
|
||||
}
|
||||
|
||||
INT_PTR LICE_GL_SubBitmap::Extended(int id, void* data)
|
||||
{
|
||||
if (!m_parent) return 0;
|
||||
|
||||
if (id == LICE_EXT_SUPPORTS_ID) return m_parent->Extended(id, data);
|
||||
|
||||
LICE_Ext_SetClip_data clipdata(m_x, m_y, m_w, m_h);
|
||||
if (!m_parent->Extended(LICE_EXT_SETCLIP, &clipdata)) return 0;
|
||||
INT_PTR ret = m_parent->Extended(id, data);
|
||||
m_parent->Extended(LICE_EXT_SETCLIP, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool LICE_GLBitmap::SetClip_ext(LICE_Ext_SetClip_data* p)
|
||||
{
|
||||
if (!FramebufferToGPU()) return false;
|
||||
|
||||
if (p)
|
||||
{
|
||||
GLdouble c0[4] = { 1.0, 0.0, 0.0, -p->x };
|
||||
GLdouble c1[4] = { -1.0, 0.0, 0.0, p->x+p->w };
|
||||
GLdouble c2[4] = { 0.0, 1.0, 0.0, -p->y};
|
||||
GLdouble c3[4] = { 0.0, -1.0, 0.0, p->y+p->h };
|
||||
glClipPlane(GL_CLIP_PLANE0, c0);
|
||||
glClipPlane(GL_CLIP_PLANE1, c1);
|
||||
glClipPlane(GL_CLIP_PLANE2, c2);
|
||||
glClipPlane(GL_CLIP_PLANE3, c3);
|
||||
glEnable(GL_CLIP_PLANE0);
|
||||
glEnable(GL_CLIP_PLANE1);
|
||||
glEnable(GL_CLIP_PLANE2);
|
||||
glEnable(GL_CLIP_PLANE3);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_CLIP_PLANE0);
|
||||
glDisable(GL_CLIP_PLANE1);
|
||||
glDisable(GL_CLIP_PLANE2);
|
||||
glDisable(GL_CLIP_PLANE3);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
LICE_GLBitmap::~LICE_GLBitmap()
|
||||
{
|
||||
ReleaseFBO();
|
||||
}
|
||||
|
||||
int LICE_GLBitmap::getWidth()
|
||||
{
|
||||
return m_bmp->getWidth();
|
||||
}
|
||||
|
||||
int LICE_GLBitmap::getHeight()
|
||||
{
|
||||
return m_bmp->getHeight();
|
||||
}
|
||||
|
||||
int LICE_GLBitmap::getRowSpan()
|
||||
{
|
||||
return m_bmp->getRowSpan();
|
||||
}
|
||||
|
||||
LICE_pixel* LICE_GLBitmap::getBits()
|
||||
{
|
||||
FramebufferFromGPU();
|
||||
return m_bmp->getBits();
|
||||
}
|
||||
|
||||
bool LICE_GLBitmap::resize(int w, int h)
|
||||
{
|
||||
int oldw = getWidth();
|
||||
int oldh = getHeight();
|
||||
if (w == oldw && h == oldh) return false;
|
||||
|
||||
if (oldw == 0 && oldh == 0 && w > 0 && h > 0)
|
||||
{
|
||||
m_bmp->resize(w, h);
|
||||
CreateFBO(w, h);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_fbo || !m_tex) return m_bmp->resize(w, h);
|
||||
|
||||
OutputDebugString("GL resizing");
|
||||
|
||||
// the framebuffer/GPU transfer overhead is per-call, so it's important to be able
|
||||
// to move the entire bitmap back and forth in one call, which means keeping m_sysbmp width == rowspan
|
||||
|
||||
int oldloc = m_bufloc;
|
||||
|
||||
FramebufferFromGPU(); // copy out the GPU data (this binds the FBO so it is the rendering target)
|
||||
|
||||
glEnable(GL_TEXTURE_RECTANGLE_ARB); // enable texturing
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_tex); // bind this texture so it is the texturing target
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // we won't be scaling it for this purpose
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // size the texture
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_tex, 0); // attach the texture as the backing store for the FBO
|
||||
glDisable(GL_TEXTURE_RECTANGLE_ARB); // done texturing
|
||||
|
||||
if (!BindFBO()) return m_bmp->resize(w, h); // this tests the FBO for validity
|
||||
|
||||
static LICE_MemBitmap tmpbmp;
|
||||
tmpbmp.resize(w, h);
|
||||
LICE_Blit(&tmpbmp, m_bmp, 0, 0, 0, 0, oldw, oldh, 1.0f, LICE_BLIT_MODE_COPY);
|
||||
m_bmp->resize(0, 0); // force it to resize down
|
||||
LICE_Copy(m_bmp, &tmpbmp);
|
||||
|
||||
if (oldloc == EMPTY) m_bufloc = EMPTY; // else bufloc remains INMEM
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LICE_GLBitmap::BindFBO()
|
||||
{
|
||||
bool valid = false;
|
||||
if (m_fbo)
|
||||
{
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); // bind this FBO so it is the rendering target
|
||||
valid = (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT);
|
||||
if (valid)
|
||||
{
|
||||
int w = getWidth();
|
||||
int h = getHeight();
|
||||
glViewport(0, 0, w, h);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(0.0, w, 0.0, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReleaseFBO();
|
||||
LICE_GL_CloseCtx(); // if we fail once we're done with GL
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
void LICE_GLBitmap::ReleaseFBO()
|
||||
{
|
||||
if (m_fbo)
|
||||
{
|
||||
glDeleteFramebuffersEXT(1, &m_fbo);
|
||||
m_fbo = 0;
|
||||
}
|
||||
if (m_tex)
|
||||
{
|
||||
glDeleteTextures(1, &m_tex);
|
||||
m_tex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool LICE_GLBitmap::FramebufferToGPU()
|
||||
{
|
||||
if (BindFBO())
|
||||
{
|
||||
if (m_bufloc == INMEM)
|
||||
{
|
||||
OutputDebugString("GL to GPU");
|
||||
glDisable(GL_BLEND);
|
||||
glRasterPos2i(0, 0);
|
||||
glDrawPixels(getWidth(), getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, m_bmp->getBits());
|
||||
}
|
||||
m_bufloc = INGPU;
|
||||
}
|
||||
return (m_bufloc == INGPU);
|
||||
}
|
||||
|
||||
void LICE_GLBitmap::FramebufferFromGPU()
|
||||
{
|
||||
if (m_bufloc == INGPU && BindFBO())
|
||||
{
|
||||
OutputDebugString("GL to mem");
|
||||
glFinish();
|
||||
glReadPixels(0, 0, getWidth(), getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, m_bmp->getBits());
|
||||
}
|
||||
m_bufloc = INMEM;
|
||||
}
|
||||
|
||||
INT_PTR LICE_GLBitmap::Extended(int id, void* data)
|
||||
{
|
||||
if (id == LICE_EXT_SUPPORTS_ID)
|
||||
{
|
||||
int extid = (int) data;
|
||||
if (extid == LICE_EXT_LINE_ACCEL) return 1;
|
||||
if (extid == LICE_EXT_FILLRECT_ACCEL) return 1;
|
||||
if (extid == LICE_EXT_DRAWCBEZIER_ACCEL) return 1;
|
||||
if (extid == LICE_EXT_DRAWGLYPH_ACCEL) return 1;
|
||||
if (extid == LICE_EXT_BLIT_ACCEL) return 1;
|
||||
if (extid == LICE_EXT_SCALEDBLIT_ACCEL) return 1;
|
||||
if (extid == LICE_EXT_GETFBOTEX_ACCEL) return 1;
|
||||
if (extid == LICE_EXT_CLEAR_ACCEL) return 1;
|
||||
if (extid == LICE_EXT_DASHEDLINE_ACCEL) return 1;
|
||||
if (extid == LICE_EXT_GETPIXEL_ACCEL) return 1;
|
||||
if (extid == LICE_EXT_PUTPIXEL_ACCEL) return 1;
|
||||
if (extid == LICE_EXT_SETCLIP) return 1;
|
||||
if (extid == LICE_EXT_WINDOW_BLIT) return 1;
|
||||
if (extid == LICE_EXT_FORGET) return 1;
|
||||
if (extid == LICE_EXT_DRAWTRIANGLE_ACCEL) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (id == LICE_EXT_CLEAR_ACCEL) return Clear_accel((LICE_pixel*)data);
|
||||
if (id == LICE_EXT_LINE_ACCEL) return Line_accel((LICE_Ext_Line_acceldata*)data);
|
||||
if (id == LICE_EXT_FILLRECT_ACCEL) return FillRect_accel((LICE_Ext_FillRect_acceldata*) data);
|
||||
if (id == LICE_EXT_DRAWCBEZIER_ACCEL) return DrawCBezier_accel((LICE_Ext_DrawCBezier_acceldata*)data);
|
||||
if (id == LICE_EXT_DRAWGLYPH_ACCEL) return DrawGlyph_accel((LICE_Ext_DrawGlyph_acceldata*)data);
|
||||
if (id == LICE_EXT_BLIT_ACCEL) return Blit_accel((LICE_Ext_Blit_acceldata*)data);
|
||||
if (id == LICE_EXT_SCALEDBLIT_ACCEL) return ScaledBlit_accel((LICE_Ext_ScaledBlit_acceldata*)data);
|
||||
if (id == LICE_EXT_DASHEDLINE_ACCEL) return DashedLine_accel((LICE_Ext_DashedLine_acceldata*)data);
|
||||
if (id == LICE_EXT_GETPIXEL_ACCEL) return GetPixel_accel((LICE_Ext_GetPixel_acceldata*)data);
|
||||
if (id == LICE_EXT_PUTPIXEL_ACCEL) return PutPixel_accel((LICE_Ext_PutPixel_acceldata*)data);
|
||||
if (id == LICE_EXT_SETCLIP) return SetClip_ext((LICE_Ext_SetClip_data*)data);
|
||||
if (id == LICE_EXT_DRAWTRIANGLE_ACCEL) return DrawTriangle_accel((LICE_Ext_DrawTriangle_acceldata*)data);
|
||||
if (id == LICE_EXT_WINDOW_BLIT) return WindowBlit((LICE_Ext_WindowBlit_data*)data);
|
||||
|
||||
if (id == LICE_EXT_FORGET)
|
||||
{
|
||||
m_bufloc = EMPTY;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (id == LICE_EXT_GETFBOTEX_ACCEL)
|
||||
{
|
||||
if (FramebufferToGPU()) return m_tex;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SetGLAliasing(bool aa)
|
||||
{
|
||||
if (aa)
|
||||
{
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
}
|
||||
}
|
||||
|
||||
static void SetGLColor(LICE_pixel color, float alpha, int licemode)
|
||||
{
|
||||
int a = 255;
|
||||
if (licemode&LICE_BLIT_USE_ALPHA) a = LICE_GETA(color);
|
||||
a = (float)a*alpha;
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
glColor4ub(LICE_GETB(color), LICE_GETG(color), LICE_GETR(color), a);
|
||||
//glColor4ub(LICE_GETR(color), LICE_GETG(color), LICE_GETB(color), a);
|
||||
}
|
||||
|
||||
bool LICE_GLBitmap::Clear_accel(LICE_pixel* color)
|
||||
{
|
||||
if (!color) return false;
|
||||
LICE_pixel col = *color;
|
||||
|
||||
if (!FramebufferToGPU()) return false;
|
||||
|
||||
float r = (float)LICE_GETR(col)/255.0f;
|
||||
float g = (float)LICE_GETG(col)/255.0f;
|
||||
float b = (float)LICE_GETB(col)/255.0f;
|
||||
float a = (float)LICE_GETA(col)/255.0f;
|
||||
glClearColor(b, g, r, a);
|
||||
//glClearColor(r, g, b, a);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LICE_GLBitmap::Line_accel(LICE_Ext_Line_acceldata* p)
|
||||
{
|
||||
if (!p) return false;
|
||||
if (!FramebufferToGPU()) return false;
|
||||
|
||||
SetGLColor(p->color, p->alpha, p->mode);
|
||||
SetGLAliasing(p->aa);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
|
||||
glVertex2f(p->x1, p->y1);
|
||||
glVertex2f(p->x2, p->y2);
|
||||
|
||||
glEnd();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LICE_GLBitmap::DashedLine_accel(LICE_Ext_DashedLine_acceldata* p)
|
||||
{
|
||||
if (!p) return false;
|
||||
if (!FramebufferToGPU()) return false;
|
||||
|
||||
SetGLColor(p->color, p->alpha, p->mode);
|
||||
SetGLAliasing(p->aa);
|
||||
|
||||
glEnable(GL_LINE_STIPPLE);
|
||||
int n = (p->pxon+p->pxoff)/2; // todo properly when pxon != pxoff
|
||||
glLineStipple(n, 0xAAAA);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
|
||||
glVertex2f(p->x1, p->y1);
|
||||
glVertex2f(p->x2, p->y2);
|
||||
|
||||
glEnd();
|
||||
|
||||
glLineStipple(1, 65535);
|
||||
glDisable(GL_LINE_STIPPLE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool LICE_GLBitmap::FillRect_accel(LICE_Ext_FillRect_acceldata* p)
|
||||
{
|
||||
if (!p) return false;
|
||||
if (!FramebufferToGPU()) return false;
|
||||
|
||||
SetGLColor(p->color, p->alpha, p->mode);
|
||||
|
||||
glBegin(GL_POLYGON);
|
||||
|
||||
glVertex2i(p->x, p->y);
|
||||
glVertex2i(p->x+p->w, p->y);
|
||||
glVertex2i(p->x+p->w, p->y+p->h);
|
||||
glVertex2i(p->x, p->y+p->h);
|
||||
|
||||
glEnd();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LICE_GLBitmap::DrawCBezier_accel(LICE_Ext_DrawCBezier_acceldata* p)
|
||||
{
|
||||
if (!p) return false;
|
||||
if (!FramebufferToGPU()) return false;
|
||||
|
||||
GLUnurbsObj* nurbs = LICE_GL_GetNurbsObj();
|
||||
if (!nurbs) return false;
|
||||
|
||||
p->color = LICE_RGBA(255,255,255,255); // temp for easy ID of GL rendering
|
||||
|
||||
SetGLColor(p->color, p->alpha, p->mode);
|
||||
SetGLAliasing(p->aa);
|
||||
|
||||
float ctlpts[] =
|
||||
{
|
||||
p->xstart, p->ystart, 0.0f,
|
||||
p->xctl1, p->yctl1, 0.0f,
|
||||
p->xctl2, p->yctl2, 0.0f,
|
||||
p->xend, p->yend, 0.0f
|
||||
};
|
||||
float knots[] = { 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
|
||||
gluBeginCurve(nurbs);
|
||||
gluNurbsCurve(nurbs, 8, knots, 3, ctlpts, 4, GL_MAP1_VERTEX_3);
|
||||
gluEndCurve(nurbs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LICE_GLBitmap::DrawGlyph_accel(LICE_Ext_DrawGlyph_acceldata* p)
|
||||
{
|
||||
if (!p) return false;
|
||||
if (!FramebufferToGPU()) return false;
|
||||
|
||||
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
|
||||
int texID = LICE_GL_GetTexFromGlyph(p->alphas, p->glyph_w, p->glyph_h);
|
||||
if (!texID) return false;
|
||||
|
||||
SetGLColor(p->color, p->alpha, p->mode);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texID);
|
||||
glBegin(GL_POLYGON);
|
||||
|
||||
glTexCoord2i(0, 0);
|
||||
glVertex2i(p->x, p->y);
|
||||
glTexCoord2i(p->glyph_w, 0);
|
||||
glVertex2i(p->x+p->glyph_w, p->y);
|
||||
glTexCoord2i(p->glyph_w, p->glyph_h);
|
||||
glVertex2i(p->x+p->glyph_w, p->y+p->glyph_h);
|
||||
glTexCoord2i(0, p->glyph_h);
|
||||
glVertex2i(p->x, p->y+p->glyph_h);
|
||||
|
||||
glEnd();
|
||||
|
||||
glDisable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LICE_GLBitmap::Blit_accel(LICE_Ext_Blit_acceldata* p)
|
||||
{
|
||||
if (!p || !p->src) return false;
|
||||
if (!FramebufferToGPU()) return false;
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
GLuint src_tex = p->src->Extended(LICE_EXT_GETFBOTEX_ACCEL, 0); // this binds the src's FBO
|
||||
if (src_tex)
|
||||
{
|
||||
if (!BindFBO()) return false; // re-bind dest FBO
|
||||
|
||||
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, src_tex);
|
||||
glBegin(GL_POLYGON);
|
||||
|
||||
glTexCoord2i(p->srcx, p->srcy);
|
||||
glVertex2i(p->dstx, p->dsty);
|
||||
glTexCoord2i(p->srcx+p->srcw, p->srcy);
|
||||
glVertex2i(p->dstx+p->srcw, p->dsty);
|
||||
glTexCoord2i(p->srcx+p->srcw, p->srcy+p->srch);
|
||||
glVertex2i(p->dstx+p->srcw, p->dsty+p->srch);
|
||||
glTexCoord2i(p->srcx, p->srcy+p->srch);
|
||||
glVertex2i(p->dstx, p->dsty+p->srch);
|
||||
|
||||
glEnd();
|
||||
|
||||
glDisable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int srcspan = p->src->getRowSpan();
|
||||
if (p->srcx == 0 && p->srcy == 0 && p->srcw == srcspan)
|
||||
{
|
||||
glRasterPos2i(p->dstx, p->dsty);
|
||||
glDrawPixels(p->srcw, p->srch, GL_RGBA, GL_UNSIGNED_BYTE, p->src->getBits());
|
||||
return true;
|
||||
}
|
||||
|
||||
LICE_pixel* srcrow = p->src->getBits()+p->srcy*srcspan+p->srcx;
|
||||
int y;
|
||||
for (y = 0; y < p->srch; ++y, srcrow += srcspan)
|
||||
{
|
||||
glRasterPos2i(p->dstx, p->dsty+y);
|
||||
glDrawPixels(p->srcw, 1, GL_RGBA, GL_UNSIGNED_BYTE, srcrow);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LICE_GLBitmap::ScaledBlit_accel(LICE_Ext_ScaledBlit_acceldata* p)
|
||||
{
|
||||
if (!p || !p->src) return false;
|
||||
if (!FramebufferToGPU()) return false;
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
|
||||
GLuint src_tex = p->src->Extended(LICE_EXT_GETFBOTEX_ACCEL, 0); // this binds the src's FBO
|
||||
bool src_has_tex = (src_tex > 0);
|
||||
if (src_has_tex)
|
||||
{
|
||||
if (!BindFBO()) return false; // re-bind dest FBO
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, src_tex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create texture from src bits
|
||||
glGenTextures(1, &src_tex);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, src_tex);
|
||||
|
||||
int srcspan = p->src->getRowSpan();
|
||||
if (p->srcx == 0 && p->srcy == 0 && srcspan == p->srcw)
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, p->srcw, p->srch, 0, GL_RGBA, GL_UNSIGNED_BYTE, p->src->getBits());
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, p->srcw, p->srch, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // size the texture
|
||||
LICE_pixel* srcrow = p->src->getBits()+(int)p->srcy*srcspan+(int)p->srcx;
|
||||
int y;
|
||||
for (y = 0; y < p->srch; ++y, srcrow += srcspan)
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, y, p->srcw, 1, GL_RGBA, GL_UNSIGNED_BYTE, srcrow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!src_tex) return false;
|
||||
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // filter
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glBegin(GL_POLYGON);
|
||||
|
||||
glTexCoord2i(p->srcx, p->srcy);
|
||||
glVertex2i(p->dstx, p->dsty);
|
||||
glTexCoord2i(p->srcx+p->srcw, p->srcy);
|
||||
glVertex2i(p->dstx+p->dstw, p->dsty);
|
||||
glTexCoord2i(p->srcx+p->srcw, p->srcy+p->srch);
|
||||
glVertex2i(p->dstx+p->dstw, p->dsty+p->dsth);
|
||||
glTexCoord2i(p->srcx, p->srcy+p->srch);
|
||||
glVertex2i(p->dstx, p->dsty+p->dsth);
|
||||
|
||||
glEnd();
|
||||
|
||||
if (!src_has_tex) glDeleteTextures(1, &src_tex);
|
||||
|
||||
glDisable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LICE_GLBitmap::GetPixel_accel(LICE_Ext_GetPixel_acceldata* p)
|
||||
{
|
||||
if (!p) return false;
|
||||
if (!FramebufferToGPU()) return false;
|
||||
|
||||
p->px = 0;
|
||||
glReadPixels(p->x, p->y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &p->px);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LICE_GLBitmap::PutPixel_accel(LICE_Ext_PutPixel_acceldata* p)
|
||||
{
|
||||
if (!p) return false;
|
||||
if (!FramebufferToGPU()) return false;
|
||||
|
||||
SetGLColor(p->color, p->alpha, p->mode);
|
||||
|
||||
glBegin(GL_POINTS);
|
||||
glVertex2i(p->x, p->y);
|
||||
glEnd();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LICE_GLBitmap::DrawTriangle_accel(LICE_Ext_DrawTriangle_acceldata *p)
|
||||
{
|
||||
if (!p) return false;
|
||||
if (!FramebufferToGPU()) return false;
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
// todo: finish implementing zbuffering, (multi)texture mapping, alpha, etc
|
||||
glColor4f(p->VertexShades[0][0],
|
||||
p->VertexShades[0][1],
|
||||
p->VertexShades[0][2],
|
||||
p->mat->SolidOpacity);
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
|
||||
int x;
|
||||
for(x=0;x<3;x++)
|
||||
{
|
||||
glVertex2i(p->scrx[x], p->scry[x]);
|
||||
}
|
||||
|
||||
glEnd();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LICE_GLBitmap::WindowBlit(LICE_Ext_WindowBlit_data* p)
|
||||
{
|
||||
if (!p) return false;
|
||||
if (!FramebufferToGPU()) return false;
|
||||
|
||||
HWND hwnd = p->hwnd;
|
||||
if (hwnd != LICE_GL_GetWindow()) return 0;
|
||||
|
||||
glFinish();
|
||||
|
||||
//HDC dc = GetDC(hwnd);
|
||||
//HGLRC rc = wglCreateContext(dc);
|
||||
//wglMakeCurrent(dc, rc);
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
|
||||
/*
|
||||
glViewport(0, 0, w, h);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(0.0, w, 0.0, h);
|
||||
*/
|
||||
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_tex);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
// the src image is upside down
|
||||
// todo positioning
|
||||
glBegin(GL_POLYGON);
|
||||
glTexCoord2i(0, p->h);
|
||||
glVertex2i(0, 0);
|
||||
glTexCoord2i(p->w, p->h);
|
||||
glVertex2i(p->w, 0);
|
||||
glTexCoord2i(p->w, 0);
|
||||
glVertex2i(p->w-1, p->h);
|
||||
glTexCoord2i(0, 0);
|
||||
glVertex2i(0, p->h);
|
||||
glEnd();
|
||||
glDisable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
|
||||
//wglMakeCurrent(0, 0);
|
||||
//wglDeleteContext(rc);
|
||||
|
||||
// ReleaseDC(hwnd, dc);
|
||||
|
||||
return true;
|
||||
}
|
||||
110
oversampling/WDL/lice/lice_glbitmap.h
Normal file
110
oversampling/WDL/lice/lice_glbitmap.h
Normal file
@@ -0,0 +1,110 @@
|
||||
#include "lice.h"
|
||||
#include "lice_extended.h"
|
||||
|
||||
// interface class for LICE_GL_SysBitmap and LICE_GL_MemBitmap
|
||||
class LICE_GLBitmap : public LICE_IBitmap
|
||||
{
|
||||
public:
|
||||
|
||||
LICE_GLBitmap();
|
||||
~LICE_GLBitmap();
|
||||
|
||||
LICE_pixel* getBits();
|
||||
|
||||
int getWidth();
|
||||
int getHeight();
|
||||
int getRowSpan();
|
||||
|
||||
bool resize(int w, int h);
|
||||
|
||||
virtual HDC getDC() = 0; // re-virtualize this to prevent instantiating LICE_GLBitmap directly
|
||||
|
||||
INT_PTR Extended(int id, void* data);
|
||||
|
||||
private:
|
||||
|
||||
bool Clear_accel(LICE_pixel* color);
|
||||
bool Line_accel(LICE_Ext_Line_acceldata* p);
|
||||
bool FillRect_accel(LICE_Ext_FillRect_acceldata* p);
|
||||
bool DrawCBezier_accel(LICE_Ext_DrawCBezier_acceldata* p);
|
||||
bool DrawGlyph_accel(LICE_Ext_DrawGlyph_acceldata* p);
|
||||
bool Blit_accel(LICE_Ext_Blit_acceldata* p);
|
||||
bool ScaledBlit_accel(LICE_Ext_ScaledBlit_acceldata* p);
|
||||
bool DashedLine_accel(LICE_Ext_DashedLine_acceldata* p);
|
||||
bool GetPixel_accel(LICE_Ext_GetPixel_acceldata* p);
|
||||
bool PutPixel_accel(LICE_Ext_PutPixel_acceldata* p);
|
||||
bool SetClip_ext(LICE_Ext_SetClip_data* p);
|
||||
bool DrawTriangle_accel(LICE_Ext_DrawTriangle_acceldata *p);
|
||||
// etc
|
||||
|
||||
bool WindowBlit(LICE_Ext_WindowBlit_data* p);
|
||||
|
||||
bool CreateFBO(int w, int h);
|
||||
bool BindFBO(); // bind this FBO so it is the current rendering target, and test for validity
|
||||
void ReleaseFBO();
|
||||
|
||||
unsigned int m_fbo; // framebuffer object: rendering target for drawing on this glbitmap
|
||||
unsigned int m_tex; // texture object: backing store for this framebuffer object
|
||||
|
||||
enum { EMPTY, INGPU, INMEM };
|
||||
int m_bufloc; // where is the current framebuffer?
|
||||
LICE_IBitmap* m_bmp;
|
||||
|
||||
protected:
|
||||
|
||||
void Init(LICE_IBitmap* bmp, int w, int h);
|
||||
bool FramebufferToGPU();
|
||||
void FramebufferFromGPU();
|
||||
};
|
||||
|
||||
class LICE_GL_SysBitmap : public LICE_GLBitmap
|
||||
{
|
||||
public:
|
||||
|
||||
LICE_GL_SysBitmap(int w=0, int h=0);
|
||||
|
||||
HDC getDC();
|
||||
|
||||
private:
|
||||
|
||||
LICE_SysBitmap m_sysbmp;
|
||||
};
|
||||
|
||||
|
||||
class LICE_GL_MemBitmap : public LICE_GLBitmap
|
||||
{
|
||||
public:
|
||||
|
||||
LICE_GL_MemBitmap(int w=0, int h=0);
|
||||
|
||||
HDC getDC() { return 0; }
|
||||
|
||||
private:
|
||||
|
||||
LICE_MemBitmap m_membmp;
|
||||
};
|
||||
|
||||
|
||||
class LICE_GL_SubBitmap : public LICE_IBitmap
|
||||
{
|
||||
public:
|
||||
|
||||
LICE_GL_SubBitmap(LICE_IBitmap *parent, int x, int y, int w, int h);
|
||||
|
||||
LICE_pixel* getBits();
|
||||
|
||||
int getWidth() { return m_w; }
|
||||
int getHeight() { return m_h; }
|
||||
int getRowSpan() { return (m_parent ? m_parent->getRowSpan() : 0); }
|
||||
|
||||
bool resize(int w, int h);
|
||||
|
||||
HDC getDC() { return (m_parent ? m_parent->getDC() : 0); }
|
||||
|
||||
INT_PTR Extended(int id, void* data);
|
||||
|
||||
private:
|
||||
|
||||
LICE_IBitmap* m_parent;
|
||||
int m_x, m_y, m_w, m_h;
|
||||
};
|
||||
191
oversampling/WDL/lice/lice_ico.cpp
Normal file
191
oversampling/WDL/lice/lice_ico.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
Cockos WDL - LICE - Lightweight Image Compositing Engine
|
||||
Copyright (C) 2007 and later, Cockos Incorporated
|
||||
File: lice_ico.cpp (ICO icon file loading for LICE)
|
||||
See lice.h for license and other information
|
||||
|
||||
This file contains some code from Microsoft's MSDN ICO loading sample
|
||||
see: http://msdn2.microsoft.com/en-us/library/ms997538.aspx
|
||||
*/
|
||||
|
||||
#include "lice.h"
|
||||
#include "../wdltypes.h"
|
||||
#ifndef _WIN32
|
||||
#include "../swell/swell.h"
|
||||
#endif
|
||||
|
||||
static LICE_IBitmap *icoToBitmap(HICON icon, LICE_IBitmap *bmpOut)
|
||||
{
|
||||
int icon_w = 16, icon_h=16;
|
||||
|
||||
#ifdef _WIN32
|
||||
ICONINFO ii={0,};
|
||||
if (GetIconInfo(icon,&ii))
|
||||
{
|
||||
bool blah=false;
|
||||
if (ii.hbmColor)
|
||||
{
|
||||
BITMAP bm={0,};
|
||||
if (GetObject(ii.hbmColor,sizeof(bm),&bm) && bm.bmWidth && bm.bmHeight)
|
||||
{
|
||||
icon_w=bm.bmWidth;
|
||||
icon_h=bm.bmHeight;
|
||||
blah=true;
|
||||
}
|
||||
DeleteObject(ii.hbmColor);
|
||||
}
|
||||
if (ii.hbmMask)
|
||||
{
|
||||
BITMAP bm={0,};
|
||||
if (!blah && GetObject(ii.hbmMask,sizeof(bm),&bm) && bm.bmWidth && bm.bmHeight)
|
||||
{
|
||||
icon_w=bm.bmWidth;
|
||||
icon_h=bm.bmHeight;
|
||||
}
|
||||
DeleteObject(ii.hbmMask);
|
||||
}
|
||||
}
|
||||
#else
|
||||
BITMAP bm={0,};
|
||||
if (GetObject(icon,sizeof(bm),&bm) && bm.bmWidth && bm.bmHeight) // SWELL's GetObject() works on icons
|
||||
{
|
||||
icon_w=bm.bmWidth;
|
||||
icon_h=bm.bmHeight;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
LICE_SysBitmap tempbm(icon_w*2,icon_h);
|
||||
LICE_FillRect(&tempbm,0,0,icon_w,icon_h,LICE_RGBA(0,0,0,255),1.0f,LICE_BLIT_MODE_COPY);
|
||||
#ifdef _WIN32
|
||||
DrawIconEx(tempbm.getDC(),0,0,icon,icon_w,icon_h,0,NULL,DI_NORMAL);
|
||||
#else
|
||||
{
|
||||
RECT r={0,0,icon_w,icon_h};
|
||||
DrawImageInRect(tempbm.getDC(),icon,&r);
|
||||
}
|
||||
#endif
|
||||
|
||||
LICE_FillRect(&tempbm,icon_w,0,icon_w,icon_h,LICE_RGBA(255,255,255,255),1.0f,LICE_BLIT_MODE_COPY);
|
||||
#ifdef _WIN32
|
||||
DrawIconEx(tempbm.getDC(),icon_w,0,icon,icon_w,icon_h,0,NULL,DI_NORMAL);
|
||||
#else
|
||||
{
|
||||
RECT r={icon_w,0,icon_w+icon_w,icon_h};
|
||||
DrawImageInRect(tempbm.getDC(),icon,&r);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!bmpOut) bmpOut = new WDL_NEW LICE_MemBitmap(icon_w,icon_h);
|
||||
else bmpOut->resize(icon_w,icon_h);
|
||||
|
||||
int y; // since we have the image drawn on white and on black, we can calculate the alpha channel...
|
||||
if (bmpOut) for(y=0;y<icon_h;y++)
|
||||
{
|
||||
int x;
|
||||
for(x=0;x<icon_w;x++)
|
||||
{
|
||||
LICE_pixel p = LICE_GetPixel(&tempbm,x,y);
|
||||
LICE_pixel p2 = LICE_GetPixel(&tempbm,x+icon_w,y);
|
||||
|
||||
int r1=LICE_GETR(p);
|
||||
int g1=LICE_GETG(p);
|
||||
int b1=LICE_GETB(p);
|
||||
|
||||
int alpha=255 - (LICE_GETR(p2)-r1);
|
||||
if (alpha>=255) alpha=255;
|
||||
else if (alpha>0)
|
||||
{
|
||||
r1 = (r1*255)/alpha; // LICE stores its alpha channel non-premultiplied, so we need to scale these up.
|
||||
g1 = (g1*255)/alpha;
|
||||
b1 = (b1*255)/alpha;
|
||||
if (r1>255)r1=255;
|
||||
if (g1>255)g1=255;
|
||||
if (b1>255)b1=255;
|
||||
}
|
||||
else alpha=0;
|
||||
LICE_PutPixel(bmpOut,x,y,LICE_RGBA(r1,g1,b1,alpha),1.0f,LICE_BLIT_MODE_COPY);
|
||||
}
|
||||
}
|
||||
|
||||
return bmpOut;
|
||||
}
|
||||
|
||||
LICE_IBitmap *LICE_LoadIcon(const char *filename, int reqiconsz, LICE_IBitmap *bmp) // returns a bitmap (bmp if nonzero) on success
|
||||
{
|
||||
if (reqiconsz<1) reqiconsz=16;
|
||||
HICON icon = NULL;
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef WDL_NO_SUPPORT_UTF8
|
||||
#ifdef WDL_SUPPORT_WIN9X
|
||||
if (GetVersion()<0x80000000)
|
||||
#endif
|
||||
{
|
||||
WCHAR wf[2048];
|
||||
if (MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,filename,-1,wf,2048))
|
||||
icon = (HICON)LoadImageW(NULL,wf,IMAGE_ICON,reqiconsz,reqiconsz,LR_LOADFROMFILE);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!icon) icon = (HICON)LoadImage(NULL,filename,IMAGE_ICON,reqiconsz,reqiconsz,LR_LOADFROMFILE);
|
||||
|
||||
#else
|
||||
icon = (HICON)LoadNamedImage(filename,false);
|
||||
#endif
|
||||
if (!icon) return 0;
|
||||
|
||||
LICE_IBitmap *ret=icoToBitmap(icon,bmp);
|
||||
DestroyIcon(icon);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LICE_IBitmap *LICE_LoadIconFromResource(HINSTANCE hInst, const char *resid, int reqiconsz, LICE_IBitmap *bmp) // returns a bitmap (bmp if nonzero) on success
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (reqiconsz<1) reqiconsz=16;
|
||||
HICON icon = (HICON)LoadImage(hInst,resid,IMAGE_ICON,reqiconsz,reqiconsz,0);
|
||||
if (!icon) return 0;
|
||||
|
||||
LICE_IBitmap *ret=icoToBitmap(icon,bmp);
|
||||
DestroyIcon(icon);
|
||||
return ret;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class LICE_ICOLoader
|
||||
{
|
||||
public:
|
||||
_LICE_ImageLoader_rec rec;
|
||||
LICE_ICOLoader()
|
||||
{
|
||||
rec.loadfunc = loadfunc;
|
||||
rec.get_extlist = get_extlist;
|
||||
rec._next = LICE_ImageLoader_list;
|
||||
LICE_ImageLoader_list = &rec;
|
||||
}
|
||||
|
||||
static LICE_IBitmap *loadfunc(const char *filename, bool checkFileName, LICE_IBitmap *bmpbase)
|
||||
{
|
||||
if (checkFileName)
|
||||
{
|
||||
const char *p=filename;
|
||||
while (*p)p++;
|
||||
while (p>filename && *p != '\\' && *p != '/' && *p != '.') p--;
|
||||
if (stricmp(p,".ico")) return 0;
|
||||
}
|
||||
return LICE_LoadIcon(filename,16,bmpbase);
|
||||
}
|
||||
static const char *get_extlist()
|
||||
{
|
||||
return "ICO files (*.ICO)\0*.ICO\0";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
LICE_ICOLoader LICE_icoldr;
|
||||
147
oversampling/WDL/lice/lice_image.cpp
Normal file
147
oversampling/WDL/lice/lice_image.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
#include "lice.h"
|
||||
|
||||
|
||||
|
||||
LICE_IBitmap* LICE_LoadImage(const char* filename, LICE_IBitmap* bmp, bool tryIgnoreExtension)
|
||||
{
|
||||
_LICE_ImageLoader_rec *hdr = LICE_ImageLoader_list;
|
||||
while (hdr)
|
||||
{
|
||||
LICE_IBitmap *ret = hdr->loadfunc(filename,true,bmp);
|
||||
if (ret) return ret;
|
||||
hdr=hdr->_next;
|
||||
}
|
||||
if (tryIgnoreExtension)
|
||||
{
|
||||
hdr = LICE_ImageLoader_list;
|
||||
while (hdr)
|
||||
{
|
||||
LICE_IBitmap *ret = hdr->loadfunc(filename,false,bmp);
|
||||
if (ret) return ret;
|
||||
hdr=hdr->_next;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static bool grow_buf(char **buf, int *bufsz, int *wrpos, const char *rd, int len)
|
||||
{
|
||||
if (*wrpos + len > *bufsz)
|
||||
{
|
||||
char *nbuf=(char*)realloc(*buf,*bufsz = *wrpos+len+4096);
|
||||
if (!nbuf) return true; // ugh
|
||||
*buf = nbuf;
|
||||
}
|
||||
memcpy(*buf+*wrpos,rd,len);
|
||||
*wrpos+=len;
|
||||
return false;
|
||||
}
|
||||
|
||||
char *LICE_GetImageExtensionList(bool wantAllSup, bool wantAllFiles)
|
||||
{
|
||||
_LICE_ImageLoader_rec *hdr = LICE_ImageLoader_list;
|
||||
int bufsz=4096;
|
||||
int wrpos=0;
|
||||
char *buf=(char *)malloc(bufsz);
|
||||
buf[0]=buf[1]=buf[2]=0;
|
||||
|
||||
if (wantAllSup)
|
||||
{
|
||||
static const char af[]="All supported images";
|
||||
if (grow_buf(&buf,&bufsz,&wrpos,af,sizeof(af))) { free(buf); return NULL; } // fail
|
||||
|
||||
int cnt=0;
|
||||
while (hdr)
|
||||
{
|
||||
const char *rd = hdr->get_extlist();
|
||||
if (rd && *rd)
|
||||
{
|
||||
bool st=false;
|
||||
const char *p=rd;
|
||||
while (*p)
|
||||
{
|
||||
if (st)
|
||||
{
|
||||
if (cnt++)
|
||||
if (grow_buf(&buf,&bufsz,&wrpos,";",1)) { free(buf); return NULL; } // fail
|
||||
if (grow_buf(&buf,&bufsz,&wrpos,p,(int)strlen(p)+1)) { free(buf); return NULL; } // fail
|
||||
wrpos--;
|
||||
}
|
||||
while (*p) p++;
|
||||
p++;
|
||||
st=!st;
|
||||
}
|
||||
}
|
||||
hdr=hdr->_next;
|
||||
}
|
||||
|
||||
if (!cnt)
|
||||
{
|
||||
wrpos=0; // reset if nothing meaningful added
|
||||
buf[0]=buf[1]=buf[2]=0;
|
||||
}
|
||||
else wrpos++;
|
||||
|
||||
hdr = LICE_ImageLoader_list;
|
||||
}
|
||||
|
||||
while (hdr)
|
||||
{
|
||||
const char *rd = hdr->get_extlist();
|
||||
if (rd && *rd)
|
||||
{
|
||||
int len = 0;
|
||||
while (rd[len] || rd[len+1]) len++; // doublenull terminated list
|
||||
|
||||
if (len)
|
||||
{
|
||||
if (grow_buf(&buf, &bufsz, &wrpos, rd, len+2)) return buf; // fail
|
||||
wrpos--; // remove doublenull on next round
|
||||
}
|
||||
}
|
||||
hdr=hdr->_next;
|
||||
}
|
||||
if (wantAllFiles)
|
||||
{
|
||||
static const char af[]="All files (*.*)\0*.*\0";
|
||||
if (grow_buf(&buf,&bufsz,&wrpos,af,sizeof(af))) return buf; // fail
|
||||
wrpos--;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
bool LICE_ImageIsSupported(const char *filename)
|
||||
{
|
||||
const char *extension = filename;
|
||||
while (*extension)extension++;
|
||||
while (extension>=filename && *extension != '/' && *extension != '.' && *extension != '\\') extension--;
|
||||
if (extension<filename || *extension != '.') return false;
|
||||
|
||||
const size_t extlen = strlen(extension);
|
||||
|
||||
_LICE_ImageLoader_rec *hdr = LICE_ImageLoader_list;
|
||||
while (hdr)
|
||||
{
|
||||
const char *el = hdr->get_extlist();
|
||||
if (el)
|
||||
{
|
||||
while (*el) el++; // skip desc
|
||||
++el;
|
||||
|
||||
// scan rest of buffer
|
||||
while (*el)
|
||||
{
|
||||
if (!strnicmp(el,extension,extlen))
|
||||
{
|
||||
if (el[extlen] == 0|| el[extlen] == ';') return true;
|
||||
}
|
||||
el++;
|
||||
}
|
||||
}
|
||||
hdr=hdr->_next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
84
oversampling/WDL/lice/lice_import.h
Normal file
84
oversampling/WDL/lice/lice_import.h
Normal file
@@ -0,0 +1,84 @@
|
||||
#define LICE_TEXT_NO_DECLARE_CACHEDFONT
|
||||
|
||||
#ifdef LICE_IMPORT_INTERFACE_ONLY
|
||||
#define LICE_FUNC_DEF_DECL extern
|
||||
#else
|
||||
#define LICE_FUNC_DEF_DECL
|
||||
#endif
|
||||
|
||||
#include "lice_text.h"
|
||||
LICE_FUNC_DEF_DECL LICE_IBitmap *(*__LICE_CreateBitmap)(int, int, int);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_PutPixel)(LICE_IBitmap* dest, int x, int y, LICE_pixel color, float alpha, int mode);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_Line)(LICE_IBitmap *dest, int x1, int y1, int x2, int y2, LICE_pixel color, float alpha, int mode, bool aa);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_FLine)(LICE_IBitmap *dest, float x1, float y1, float x2, float y2, LICE_pixel color, float alpha, int mode, bool aa);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_DashedLine)(LICE_IBitmap *dest, int x1, int y1, int x2, int y2, int on, int off, LICE_pixel color, float alpha, int mode, bool aa);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_FillRect)(LICE_IBitmap *dest, int x, int y, int w, int h, LICE_pixel color, float alpha , int mode);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_DrawRect)(LICE_IBitmap *dest, int x, int y, int w, int h, LICE_pixel color, float alpha , int mode);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_BorderedRect)(LICE_IBitmap *dest, int x, int y, int w, int h, LICE_pixel bgcolor, LICE_pixel fgcolor, float alpha, int mode);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_Circle)(LICE_IBitmap* dest, float cx, float cy, float r, LICE_pixel color, float alpha, int mode, bool aa);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_FillCircle)(LICE_IBitmap* dest, float cx, float cy, float r, LICE_pixel color, float alpha, int mode, bool aa);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_Clear)(LICE_IBitmap *dest, LICE_pixel color);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_Blit)(LICE_IBitmap *dest, LICE_IBitmap *src, int dstx, int dsty, int srcx, int srcy, int srcw, int srch, float alpha, int mode);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_RotatedBlit)(LICE_IBitmap *dest, LICE_IBitmap *src, int dstx, int dsty, int dstw, int dsth, float srcx, float srcy, float srcw, float srch, float angle, bool cliptosourcerect, float alpha, int mode, float rotxcent, float rotycent);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_DrawGlyph)(LICE_IBitmap* dest, int x, int y, LICE_pixel color, LICE_pixel_chan* glyph, int glyph_w, int glyph_h, float alpha, int mode);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_FillTriangle)(LICE_IBitmap *dest, int x1, int y1, int x2, int y2, int x3, int y3, LICE_pixel color, float alpha, int mode);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_Arc)(LICE_IBitmap* dest, float cx, float cy, float r, float alo, float ahi, LICE_pixel color, float alpha, int mode, bool aa);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_FillTrapezoid)(LICE_IBitmap* dest, int x1a, int x1b, int y1, int x2a, int x2b, int y2, LICE_pixel color, float alpha, int mode);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_FillConvexPolygon)(LICE_IBitmap* dest, int* x, int* y, int npoints, LICE_pixel color, float alpha, int mode);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_Copy)(LICE_IBitmap* dest, LICE_IBitmap* src);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_DrawText)(LICE_IBitmap *bm, int x, int y, const char *string, LICE_pixel color, float alpha, int mode);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_MeasureText)(const char *string, int *w, int *h);
|
||||
LICE_FUNC_DEF_DECL void (*__LICE_ScaledBlit)(LICE_IBitmap *dest, LICE_IBitmap *src, int dstx, int dsty, int dstw, int dsth, float srcx, float srcy, float srcw, float srch, float alpha, int mode);
|
||||
|
||||
LICE_FUNC_DEF_DECL void * (*LICE_CreateFont)();
|
||||
#define LICE_PutPixel __LICE_PutPixel
|
||||
#define LICE_Line __LICE_Line
|
||||
#define LICE_FLine __LICE_FLine
|
||||
#define LICE_DashedLine __LICE_DashedLine
|
||||
#define LICE_FillRect __LICE_FillRect
|
||||
#define LICE_DrawRect __LICE_DrawRect
|
||||
#define LICE_Circle __LICE_Circle
|
||||
#define LICE_Clear __LICE_Clear
|
||||
#define LICE_Blit __LICE_Blit
|
||||
#define LICE_RotatedBlit __LICE_RotatedBlit
|
||||
#define LICE_DrawGlyph __LICE_DrawGlyph
|
||||
#define LICE_FillCircle __LICE_FillCircle
|
||||
#define LICE_BorderedRect __LICE_BorderedRect
|
||||
#define LICE_FillTriangle __LICE_FillTriangle
|
||||
#define LICE_Arc __LICE_Arc
|
||||
#define LICE_FillTrapezoid __LICE_FillTrapezoid
|
||||
#define LICE_FillConvexPolygon __LICE_FillConvexPolygon
|
||||
#define LICE_Copy __LICE_Copy
|
||||
#define LICE_DrawText __LICE_DrawText
|
||||
#define LICE_MeasureText __LICE_MeasureText
|
||||
#define LICE_ScaledBlit __LICE_ScaledBlit
|
||||
#define LICE_CreateMemBitmap(w,h) (__LICE_CreateBitmap ? __LICE_CreateBitmap(0,w,h) : 0)
|
||||
#define LICE_CreateSysBitmap(w,h) (__LICE_CreateBitmap ? __LICE_CreateBitmap(1,w,h) : 0)
|
||||
#define LICE_CreateTextCache() ((LICE_IFont*)(LICE_CreateFont?LICE_CreateFont():0))
|
||||
#undef LICE_FUNC_DEF_DECL
|
||||
|
||||
#define IMPORT_LICE_FUNCS(IMPORT_FUNC) \
|
||||
IMPORT_FUNC(__LICE_CreateBitmap,"LICE_CreateBitmap") \
|
||||
IMPORT_FUNC(__LICE_PutPixel,"LICE_PutPixel") \
|
||||
IMPORT_FUNC(__LICE_Line,"LICE_LineInt") \
|
||||
IMPORT_FUNC(__LICE_FLine,"LICE_Line") \
|
||||
IMPORT_FUNC(__LICE_DashedLine, "LICE_DashedLine") \
|
||||
IMPORT_FUNC(__LICE_Circle,"LICE_Circle") \
|
||||
IMPORT_FUNC(__LICE_FillCircle,"LICE_FillCircle") \
|
||||
IMPORT_FUNC(__LICE_FillRect,"LICE_FillRect") \
|
||||
IMPORT_FUNC(__LICE_DrawRect,"LICE_DrawRect") \
|
||||
IMPORT_FUNC(__LICE_BorderedRect,"LICE_BorderedRect") \
|
||||
IMPORT_FUNC(__LICE_Clear,"LICE_Clear") \
|
||||
IMPORT_FUNC(__LICE_Blit,"LICE_Blit") \
|
||||
IMPORT_FUNC(__LICE_RotatedBlit,"LICE_RotatedBlit") \
|
||||
IMPORT_FUNC(__LICE_DrawGlyph,"LICE_DrawGlyph") \
|
||||
IMPORT_FUNC(LICE_CreateFont,"LICE_CreateFont") \
|
||||
IMPORT_FUNC(LICE_FillTriangle,"LICE_FillTriangle") \
|
||||
IMPORT_FUNC(LICE_Arc,"LICE_Arc") \
|
||||
IMPORT_FUNC(LICE_FillTrapezoid,"LICE_FillTrapezoid") \
|
||||
IMPORT_FUNC(LICE_FillConvexPolygon,"LICE_FillConvexPolygon") \
|
||||
IMPORT_FUNC(LICE_Copy,"LICE_Copy") \
|
||||
IMPORT_FUNC(__LICE_ScaledBlit,"LICE_ScaledBlit") \
|
||||
IMPORT_FUNC(__LICE_MeasureText,"LICE_MeasureText") \
|
||||
IMPORT_FUNC(__LICE_DrawText,"LICE_DrawText")
|
||||
|
||||
404
oversampling/WDL/lice/lice_jpg.cpp
Normal file
404
oversampling/WDL/lice/lice_jpg.cpp
Normal file
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
Cockos WDL - LICE - Lightweight Image Compositing Engine
|
||||
Copyright (C) 2007 and later, Cockos Incorporated
|
||||
File: lice_jpg.cpp (JPG loading for LICE)
|
||||
See lice.h for license and other information
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "lice.h"
|
||||
#include <setjmp.h>
|
||||
#include "../wdltypes.h"
|
||||
|
||||
extern "C" {
|
||||
#include "../jpeglib/jpeglib.h"
|
||||
};
|
||||
|
||||
struct my_error_mgr {
|
||||
struct jpeg_error_mgr pub; /* "public" fields */
|
||||
jmp_buf setjmp_buffer; /* for return to caller */
|
||||
};
|
||||
static void LICEJPEG_Error(j_common_ptr cinfo)
|
||||
{
|
||||
longjmp(((my_error_mgr*)cinfo->err)->setjmp_buffer,1);
|
||||
}
|
||||
static void LICEJPEG_EmitMsg(j_common_ptr cinfo, int msg_level) { }
|
||||
static void LICEJPEG_FmtMsg(j_common_ptr cinfo, char *) { }
|
||||
static void LICEJPEG_OutMsg(j_common_ptr cinfo) { }
|
||||
static void LICEJPEG_reset_error_mgr(j_common_ptr cinfo)
|
||||
{
|
||||
cinfo->err->num_warnings = 0;
|
||||
cinfo->err->msg_code = 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static void LICEJPEG_init_source(j_decompress_ptr cinfo) {}
|
||||
static unsigned char EOI_data[2] = { 0xFF, 0xD9 };
|
||||
static boolean LICEJPEG_fill_input_buffer(j_decompress_ptr cinfo)
|
||||
{
|
||||
cinfo->src->next_input_byte = EOI_data;
|
||||
cinfo->src->bytes_in_buffer = 2;
|
||||
return TRUE;
|
||||
}
|
||||
static void LICEJPEG_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
|
||||
{
|
||||
if (num_bytes > 0)
|
||||
{
|
||||
if (num_bytes > (long) cinfo->src->bytes_in_buffer)
|
||||
{
|
||||
num_bytes = (long) cinfo->src->bytes_in_buffer;
|
||||
}
|
||||
cinfo->src->next_input_byte += (size_t) num_bytes;
|
||||
cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
|
||||
}
|
||||
}
|
||||
static void LICEJPEG_term_source(j_decompress_ptr cinfo) {}
|
||||
#endif
|
||||
|
||||
|
||||
LICE_IBitmap *LICE_LoadJPGFromResource(HINSTANCE hInst, const char *resid, LICE_IBitmap *bmp)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HRSRC hResource = FindResource(hInst, resid, "JPG");
|
||||
if(!hResource) return NULL;
|
||||
|
||||
DWORD imageSize = SizeofResource(hInst, hResource);
|
||||
if(imageSize < 8) return NULL;
|
||||
|
||||
HGLOBAL res = LoadResource(hInst, hResource);
|
||||
const void* pResourceData = LockResource(res);
|
||||
if(!pResourceData) return NULL;
|
||||
|
||||
unsigned char *data = (unsigned char *)pResourceData;
|
||||
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
struct my_error_mgr jerr={0,};
|
||||
JSAMPARRAY buffer;
|
||||
int row_stride;
|
||||
|
||||
jerr.pub.error_exit = LICEJPEG_Error;
|
||||
jerr.pub.emit_message = LICEJPEG_EmitMsg;
|
||||
jerr.pub.output_message = LICEJPEG_OutMsg;
|
||||
jerr.pub.format_message = LICEJPEG_FmtMsg;
|
||||
jerr.pub.reset_error_mgr = LICEJPEG_reset_error_mgr;
|
||||
|
||||
cinfo.err = &jerr.pub;
|
||||
|
||||
if (setjmp(jerr.setjmp_buffer))
|
||||
{
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return 0;
|
||||
}
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
cinfo.src = (struct jpeg_source_mgr *) (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT, sizeof (struct jpeg_source_mgr));
|
||||
|
||||
cinfo.src->init_source = LICEJPEG_init_source;
|
||||
cinfo.src->fill_input_buffer = LICEJPEG_fill_input_buffer;
|
||||
cinfo.src->skip_input_data = LICEJPEG_skip_input_data;
|
||||
cinfo.src->resync_to_restart = jpeg_resync_to_restart;
|
||||
cinfo.src->term_source = LICEJPEG_term_source;
|
||||
|
||||
cinfo.src->next_input_byte = data;
|
||||
cinfo.src->bytes_in_buffer = imageSize;
|
||||
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
row_stride = cinfo.output_width * cinfo.output_components;
|
||||
|
||||
buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
|
||||
|
||||
LICE_IBitmap *delbmp = NULL;
|
||||
if (bmp) bmp->resize(cinfo.output_width,cinfo.output_height);
|
||||
else delbmp = bmp = new WDL_NEW LICE_MemBitmap(cinfo.output_width,cinfo.output_height);
|
||||
|
||||
if (!bmp || bmp->getWidth() != (int)cinfo.output_width || bmp->getHeight() != (int)cinfo.output_height)
|
||||
{
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
delete delbmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
LICE_pixel *bmpptr = bmp->getBits();
|
||||
int dbmpptr=bmp->getRowSpan();
|
||||
if (bmp->isFlipped())
|
||||
{
|
||||
bmpptr += dbmpptr*(bmp->getHeight()-1);
|
||||
dbmpptr=-dbmpptr;
|
||||
}
|
||||
|
||||
while (cinfo.output_scanline < cinfo.output_height)
|
||||
{
|
||||
/* jpeg_read_scanlines expects an array of pointers to scanlines.
|
||||
* Here the array is only one element long, but you could ask for
|
||||
* more than one scanline at a time if that's more convenient.
|
||||
*/
|
||||
jpeg_read_scanlines(&cinfo, buffer, 1);
|
||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||
// put_scanline_someplace(buffer[0], row_stride);
|
||||
if (cinfo.output_components==3)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < (int)cinfo.output_width; x++)
|
||||
{
|
||||
bmpptr[x]=LICE_RGBA(buffer[0][x*3],buffer[0][x*3+1],buffer[0][x*3+2],255);
|
||||
}
|
||||
}
|
||||
else if (cinfo.output_components==1)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < (int)cinfo.output_width; x++)
|
||||
{
|
||||
int v=buffer[0][x];
|
||||
bmpptr[x]=LICE_RGBA(v,v,v,255);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(bmpptr,0,4*cinfo.output_width);
|
||||
}
|
||||
bmpptr+=dbmpptr;
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo); // we created cinfo.src with some special alloc so I think it gets collected
|
||||
|
||||
return bmp;
|
||||
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
LICE_IBitmap *LICE_LoadJPG(const char *filename, LICE_IBitmap *bmp)
|
||||
{
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
struct my_error_mgr jerr={{0},};
|
||||
JSAMPARRAY buffer;
|
||||
int row_stride;
|
||||
|
||||
FILE *fp=NULL;
|
||||
#if defined(_WIN32) && !defined(WDL_NO_SUPPORT_UTF8)
|
||||
#ifdef WDL_SUPPORT_WIN9X
|
||||
if (GetVersion()<0x80000000)
|
||||
#endif
|
||||
{
|
||||
WCHAR wf[2048];
|
||||
if (MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,filename,-1,wf,2048))
|
||||
fp = _wfopen(wf,L"rb");
|
||||
}
|
||||
#endif
|
||||
if (!fp) fp = WDL_fopenA(filename,"rb");
|
||||
|
||||
if (!fp) return 0;
|
||||
|
||||
jerr.pub.error_exit = LICEJPEG_Error;
|
||||
jerr.pub.emit_message = LICEJPEG_EmitMsg;
|
||||
jerr.pub.output_message = LICEJPEG_OutMsg;
|
||||
jerr.pub.format_message = LICEJPEG_FmtMsg;
|
||||
jerr.pub.reset_error_mgr = LICEJPEG_reset_error_mgr;
|
||||
|
||||
cinfo.err = &jerr.pub;
|
||||
|
||||
if (setjmp(jerr.setjmp_buffer))
|
||||
{
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
jpeg_stdio_src(&cinfo, fp);
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
row_stride = cinfo.output_width * cinfo.output_components;
|
||||
|
||||
buffer = (*cinfo.mem->alloc_sarray)
|
||||
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
|
||||
|
||||
|
||||
LICE_IBitmap *delbmp = NULL;
|
||||
if (bmp) bmp->resize(cinfo.output_width,cinfo.output_height);
|
||||
else delbmp = bmp = new WDL_NEW LICE_MemBitmap(cinfo.output_width,cinfo.output_height);
|
||||
|
||||
if (!bmp || bmp->getWidth() != (int)cinfo.output_width || bmp->getHeight() != (int)cinfo.output_height)
|
||||
{
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(fp);
|
||||
delete delbmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
LICE_pixel *bmpptr = bmp->getBits();
|
||||
int dbmpptr=bmp->getRowSpan();
|
||||
if (bmp->isFlipped())
|
||||
{
|
||||
bmpptr += dbmpptr*(bmp->getHeight()-1);
|
||||
dbmpptr=-dbmpptr;
|
||||
}
|
||||
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
/* jpeg_read_scanlines expects an array of pointers to scanlines.
|
||||
* Here the array is only one element long, but you could ask for
|
||||
* more than one scanline at a time if that's more convenient.
|
||||
*/
|
||||
jpeg_read_scanlines(&cinfo, buffer, 1);
|
||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||
// put_scanline_someplace(buffer[0], row_stride);
|
||||
if (cinfo.output_components==3)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < (int)cinfo.output_width; x++)
|
||||
{
|
||||
bmpptr[x]=LICE_RGBA(buffer[0][x*3],buffer[0][x*3+1],buffer[0][x*3+2],255);
|
||||
}
|
||||
}
|
||||
else if (cinfo.output_components==1)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < (int)cinfo.output_width; x++)
|
||||
{
|
||||
int v=buffer[0][x];
|
||||
bmpptr[x]=LICE_RGBA(v,v,v,255);
|
||||
}
|
||||
}
|
||||
else
|
||||
memset(bmpptr,0,4*cinfo.output_width);
|
||||
bmpptr+=dbmpptr;
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(fp);
|
||||
|
||||
return bmp;
|
||||
}
|
||||
|
||||
LICE_IBitmap *LICE_LoadJPGFromMemory(const void *data_in, int buflen, LICE_IBitmap *bmp)
|
||||
{
|
||||
if (buflen < 8) return NULL;
|
||||
|
||||
unsigned char *data = (unsigned char *)(void *)data_in;
|
||||
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
struct my_error_mgr jerr={{0},};
|
||||
JSAMPARRAY buffer;
|
||||
int row_stride;
|
||||
|
||||
jerr.pub.error_exit = LICEJPEG_Error;
|
||||
jerr.pub.emit_message = LICEJPEG_EmitMsg;
|
||||
jerr.pub.output_message = LICEJPEG_OutMsg;
|
||||
jerr.pub.format_message = LICEJPEG_FmtMsg;
|
||||
jerr.pub.reset_error_mgr = LICEJPEG_reset_error_mgr;
|
||||
|
||||
cinfo.err = &jerr.pub;
|
||||
|
||||
if (setjmp(jerr.setjmp_buffer))
|
||||
{
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return 0;
|
||||
}
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
jpeg_mem_src(&cinfo, data, buflen);
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
row_stride = cinfo.output_width * cinfo.output_components;
|
||||
|
||||
buffer = (*cinfo.mem->alloc_sarray)
|
||||
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
|
||||
|
||||
|
||||
LICE_IBitmap *delbmp = NULL;
|
||||
if (bmp) bmp->resize(cinfo.output_width,cinfo.output_height);
|
||||
else delbmp = bmp = new WDL_NEW LICE_MemBitmap(cinfo.output_width,cinfo.output_height);
|
||||
|
||||
if (!bmp || bmp->getWidth() != (int)cinfo.output_width || bmp->getHeight() != (int)cinfo.output_height)
|
||||
{
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
delete delbmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
LICE_pixel *bmpptr = bmp->getBits();
|
||||
int dbmpptr=bmp->getRowSpan();
|
||||
if (bmp->isFlipped())
|
||||
{
|
||||
bmpptr += dbmpptr*(bmp->getHeight()-1);
|
||||
dbmpptr=-dbmpptr;
|
||||
}
|
||||
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
/* jpeg_read_scanlines expects an array of pointers to scanlines.
|
||||
* Here the array is only one element long, but you could ask for
|
||||
* more than one scanline at a time if that's more convenient.
|
||||
*/
|
||||
jpeg_read_scanlines(&cinfo, buffer, 1);
|
||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||
// put_scanline_someplace(buffer[0], row_stride);
|
||||
if (cinfo.output_components==3)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < (int)cinfo.output_width; x++)
|
||||
{
|
||||
bmpptr[x]=LICE_RGBA(buffer[0][x*3],buffer[0][x*3+1],buffer[0][x*3+2],255);
|
||||
}
|
||||
}
|
||||
else if (cinfo.output_components==1)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < (int)cinfo.output_width; x++)
|
||||
{
|
||||
int v=buffer[0][x];
|
||||
bmpptr[x]=LICE_RGBA(v,v,v,255);
|
||||
}
|
||||
}
|
||||
else
|
||||
memset(bmpptr,0,4*cinfo.output_width);
|
||||
bmpptr+=dbmpptr;
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
return bmp;
|
||||
}
|
||||
|
||||
class LICE_JPGLoader
|
||||
{
|
||||
public:
|
||||
_LICE_ImageLoader_rec rec;
|
||||
LICE_JPGLoader()
|
||||
{
|
||||
rec.loadfunc = loadfunc;
|
||||
rec.get_extlist = get_extlist;
|
||||
rec._next = LICE_ImageLoader_list;
|
||||
LICE_ImageLoader_list = &rec;
|
||||
}
|
||||
|
||||
static LICE_IBitmap *loadfunc(const char *filename, bool checkFileName, LICE_IBitmap *bmpbase)
|
||||
{
|
||||
if (checkFileName)
|
||||
{
|
||||
const char *p=filename;
|
||||
while (*p)p++;
|
||||
while (p>filename && *p != '\\' && *p != '/' && *p != '.') p--;
|
||||
if (stricmp(p,".jpg")&&stricmp(p,".jpeg")&&stricmp(p,".jfif")) return 0;
|
||||
}
|
||||
return LICE_LoadJPG(filename,bmpbase);
|
||||
}
|
||||
static const char *get_extlist()
|
||||
{
|
||||
return "JPEG files (*.JPG;*.JPEG;*.JFIF)\0*.JPG;*.JPEG;*.JFIF\0";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
LICE_JPGLoader LICE_jgpldr;
|
||||
119
oversampling/WDL/lice/lice_jpg_write.cpp
Normal file
119
oversampling/WDL/lice/lice_jpg_write.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
Cockos WDL - LICE - Lightweight Image Compositing Engine
|
||||
Copyright (C) 2007 and later, Cockos Incorporated
|
||||
File: lice_jpg_write.cpp (JPG writing for LICE)
|
||||
See lice.h for license and other information
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "lice.h"
|
||||
#include <setjmp.h>
|
||||
|
||||
extern "C" {
|
||||
#include "../jpeglib/jpeglib.h"
|
||||
};
|
||||
|
||||
struct my_error_mgr {
|
||||
struct jpeg_error_mgr pub; /* "public" fields */
|
||||
jmp_buf setjmp_buffer; /* for return to caller */
|
||||
};
|
||||
static void LICEJPEG_Error(j_common_ptr cinfo)
|
||||
{
|
||||
longjmp(((my_error_mgr*)cinfo->err)->setjmp_buffer,1);
|
||||
}
|
||||
static void LICEJPEG_EmitMsg(j_common_ptr cinfo, int msg_level) { }
|
||||
static void LICEJPEG_FmtMsg(j_common_ptr cinfo, char *) { }
|
||||
static void LICEJPEG_OutMsg(j_common_ptr cinfo) { }
|
||||
static void LICEJPEG_reset_error_mgr(j_common_ptr cinfo)
|
||||
{
|
||||
cinfo->err->num_warnings = 0;
|
||||
cinfo->err->msg_code = 0;
|
||||
}
|
||||
|
||||
bool LICE_WriteJPG(const char *filename, LICE_IBitmap *bmp, int quality, bool force_baseline)
|
||||
{
|
||||
if (!bmp || !filename) return false;
|
||||
|
||||
FILE *fp=NULL;
|
||||
#if defined(_WIN32) && !defined(WDL_NO_SUPPORT_UTF8)
|
||||
#ifdef WDL_SUPPORT_WIN9X
|
||||
if (GetVersion()<0x80000000)
|
||||
#endif
|
||||
{
|
||||
WCHAR wf[2048];
|
||||
if (MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,filename,-1,wf,2048))
|
||||
fp = _wfopen(wf,L"wb");
|
||||
}
|
||||
#endif
|
||||
if (!fp) fp = fopen(filename,"wb");
|
||||
|
||||
if (!fp) return false;
|
||||
|
||||
struct jpeg_compress_struct cinfo;
|
||||
struct my_error_mgr jerr={0,};
|
||||
jerr.pub.error_exit = LICEJPEG_Error;
|
||||
jerr.pub.emit_message = LICEJPEG_EmitMsg;
|
||||
jerr.pub.output_message = LICEJPEG_OutMsg;
|
||||
jerr.pub.format_message = LICEJPEG_FmtMsg;
|
||||
jerr.pub.reset_error_mgr = LICEJPEG_reset_error_mgr;
|
||||
|
||||
cinfo.err = &jerr.pub;
|
||||
unsigned char *buf = NULL;
|
||||
|
||||
if (setjmp(jerr.setjmp_buffer))
|
||||
{
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
if (fp) fclose(fp);
|
||||
free(buf);
|
||||
return false;
|
||||
}
|
||||
jpeg_create_compress(&cinfo);
|
||||
|
||||
jpeg_stdio_dest(&cinfo, fp);
|
||||
|
||||
cinfo.image_width = bmp->getWidth(); /* image width and height, in pixels */
|
||||
cinfo.image_height = bmp->getHeight();
|
||||
cinfo.input_components = 3; /* # of color components per pixel */
|
||||
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
|
||||
|
||||
jpeg_set_defaults(&cinfo);
|
||||
jpeg_set_quality(&cinfo, quality, !!force_baseline);
|
||||
jpeg_start_compress(&cinfo, TRUE);
|
||||
|
||||
buf = (unsigned char *)malloc(cinfo.image_width * 3);
|
||||
LICE_pixel_chan *rd = (LICE_pixel_chan *)bmp->getBits();
|
||||
int rowspan = bmp->getRowSpan()*4;
|
||||
if (bmp->isFlipped())
|
||||
{
|
||||
rd += rowspan*(bmp->getHeight()-1);
|
||||
rowspan=-rowspan;
|
||||
}
|
||||
while (cinfo.next_scanline < cinfo.image_height)
|
||||
{
|
||||
unsigned char *outp=buf;
|
||||
LICE_pixel_chan *rdp = rd;
|
||||
int x=cinfo.image_width;
|
||||
while(x--)
|
||||
{
|
||||
outp[0] = rdp[LICE_PIXEL_R];
|
||||
outp[1] = rdp[LICE_PIXEL_G];
|
||||
outp[2] = rdp[LICE_PIXEL_B];
|
||||
outp+=3;
|
||||
rdp+=4;
|
||||
}
|
||||
jpeg_write_scanlines(&cinfo, &buf, 1);
|
||||
|
||||
rd+=rowspan;
|
||||
}
|
||||
free(buf);
|
||||
buf=0;
|
||||
|
||||
jpeg_finish_compress(&cinfo);
|
||||
|
||||
if (fp) fclose(fp);
|
||||
fp=0;
|
||||
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
673
oversampling/WDL/lice/lice_lcf.cpp
Normal file
673
oversampling/WDL/lice/lice_lcf.cpp
Normal file
@@ -0,0 +1,673 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "lice_lcf.h"
|
||||
|
||||
#include "../filewrite.h"
|
||||
#include "../fileread.h"
|
||||
|
||||
|
||||
#define LCF_VERSION 0x11CEb001
|
||||
|
||||
LICECaptureCompressor::LICECaptureCompressor(const char *outfn, int w, int h, int interval, int bsize_w, int bsize_h)
|
||||
{
|
||||
m_inframes = m_outframes=0;
|
||||
m_file = new WDL_FileWrite(outfn,1,512*1024);
|
||||
if (!m_file->IsOpen()) { delete m_file; m_file=0; }
|
||||
|
||||
memset(&m_compstream,0,sizeof(m_compstream));
|
||||
if (m_file)
|
||||
{
|
||||
if (deflateInit(&m_compstream,9)!=Z_OK)
|
||||
{
|
||||
delete m_file;
|
||||
m_file=0;
|
||||
}
|
||||
}
|
||||
|
||||
m_inbytes=0;
|
||||
m_outsize=0;
|
||||
m_w=w;
|
||||
m_h=h;
|
||||
m_interval=interval;
|
||||
m_bsize_w=bsize_w;
|
||||
m_bsize_h=bsize_h;
|
||||
m_state=0;
|
||||
m_which=0;
|
||||
m_outchunkpos=0;
|
||||
m_numcols = (m_w+bsize_w-1) / (bsize_w>0?bsize_w:1);
|
||||
if (m_numcols<1) m_numcols=1;
|
||||
m_numrows = (m_h+bsize_h-1)/ (bsize_h>0?bsize_h:1);
|
||||
|
||||
m_current_block_srcsize=0;
|
||||
}
|
||||
|
||||
void LICECaptureCompressor::OnFrame(LICE_IBitmap *fr, int delta_t_ms)
|
||||
{
|
||||
if (fr)
|
||||
{
|
||||
if (fr->getWidth()!=m_w || fr->getHeight()!=m_h) return;
|
||||
|
||||
frameRec *rec = m_framelists[m_which].Get(m_state);
|
||||
if (!rec)
|
||||
{
|
||||
rec = new frameRec(m_w*m_h);
|
||||
m_framelists[m_which].Add(rec);
|
||||
}
|
||||
rec->delta_t_ms=delta_t_ms;
|
||||
BitmapToFrameRec(fr,rec);
|
||||
m_state++;
|
||||
m_inframes++;
|
||||
}
|
||||
|
||||
|
||||
bool isLastBlock = m_state >= m_interval || !fr;
|
||||
|
||||
if (m_framelists[!m_which].GetSize())
|
||||
{
|
||||
int compressTo;
|
||||
if (isLastBlock) compressTo = m_numcols*m_numrows;
|
||||
else compressTo = (m_state * m_numcols*m_numrows) / m_interval;
|
||||
|
||||
frameRec **list = m_framelists[!m_which].GetList();
|
||||
int list_size = m_framelists[!m_which].GetSize();
|
||||
|
||||
// compress some data
|
||||
int chunkpos = m_outchunkpos;
|
||||
while (chunkpos < compressTo)
|
||||
{
|
||||
int xpos = (chunkpos%m_numcols) * m_bsize_w;
|
||||
int ypos = (chunkpos/m_numcols) * m_bsize_h;
|
||||
|
||||
int wid = m_w-xpos;
|
||||
int hei = m_h-ypos;
|
||||
if (wid > m_bsize_w) wid=m_bsize_w;
|
||||
if (hei > m_bsize_h) hei=m_bsize_h;
|
||||
|
||||
int i;
|
||||
int rdoffs = xpos + ypos*m_w;
|
||||
int rdspan = m_w;
|
||||
|
||||
int repeat_cnt=0;
|
||||
|
||||
for(i=0;i<list_size; i++)
|
||||
{
|
||||
unsigned short *rd = list[i]->data + rdoffs;
|
||||
if (i&&repeat_cnt<255)
|
||||
{
|
||||
unsigned short *rd1=rd;
|
||||
unsigned short *rd2=list[i-1]->data+rdoffs;
|
||||
int a=hei;
|
||||
while(a--)
|
||||
{
|
||||
if (memcmp(rd1,rd2,wid*sizeof(short))) break;
|
||||
rd1+=rdspan;
|
||||
rd2+=rdspan;
|
||||
}
|
||||
if (a<0)
|
||||
{
|
||||
repeat_cnt++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (i || repeat_cnt)
|
||||
{
|
||||
unsigned char c = (unsigned char)repeat_cnt;
|
||||
DeflateBlock(&c,1,false);
|
||||
repeat_cnt=0;
|
||||
}
|
||||
int a=hei;
|
||||
while (a--)
|
||||
{
|
||||
DeflateBlock(rd,wid*sizeof(short),false);
|
||||
rd+=rdspan;
|
||||
}
|
||||
}
|
||||
if (repeat_cnt)
|
||||
{
|
||||
unsigned char c = (unsigned char)repeat_cnt;
|
||||
DeflateBlock(&c,1,false);
|
||||
}
|
||||
|
||||
chunkpos++;
|
||||
}
|
||||
m_outchunkpos=chunkpos;
|
||||
}
|
||||
|
||||
if (isLastBlock)
|
||||
{
|
||||
if (m_framelists[!m_which].GetSize())
|
||||
{
|
||||
m_outframes += m_framelists[!m_which].GetSize();
|
||||
|
||||
DeflateBlock(NULL,0,true);
|
||||
|
||||
deflateReset(&m_compstream);
|
||||
|
||||
m_hdrqueue.Clear();
|
||||
AddHdrInt(LCF_VERSION);
|
||||
AddHdrInt(16);
|
||||
AddHdrInt(m_w);
|
||||
AddHdrInt(m_h);
|
||||
AddHdrInt(m_bsize_w);
|
||||
AddHdrInt(m_bsize_h);
|
||||
int nf = m_framelists[!m_which].GetSize();
|
||||
AddHdrInt(nf);
|
||||
int sz = m_current_block.Available();
|
||||
AddHdrInt(sz);
|
||||
|
||||
int uncomp_sz = m_current_block_srcsize;
|
||||
AddHdrInt(uncomp_sz);
|
||||
|
||||
{
|
||||
int x;
|
||||
for(x=0;x<nf;x++)
|
||||
{
|
||||
AddHdrInt(m_framelists[!m_which].Get(x)->delta_t_ms);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
m_file->Write(m_hdrqueue.Get(),m_hdrqueue.Available());
|
||||
m_outsize += m_hdrqueue.Available();
|
||||
m_file->Write(m_current_block.Get(),sz);
|
||||
m_outsize += sz;
|
||||
|
||||
m_current_block.Clear();
|
||||
m_current_block_srcsize=0;
|
||||
}
|
||||
|
||||
|
||||
int old_state=m_state;
|
||||
m_state=0;
|
||||
m_outchunkpos=0;
|
||||
m_which=!m_which;
|
||||
|
||||
|
||||
if (old_state>0 && !fr)
|
||||
{
|
||||
while (m_framelists[!m_which].GetSize() > old_state)
|
||||
m_framelists[!m_which].Delete(m_framelists[!m_which].GetSize()-1,true);
|
||||
|
||||
OnFrame(NULL,0);
|
||||
}
|
||||
|
||||
if (!fr)
|
||||
{
|
||||
m_framelists[0].Empty(true);
|
||||
m_framelists[1].Empty(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LICECaptureCompressor::BitmapToFrameRec(LICE_IBitmap *fr, frameRec *dest)
|
||||
{
|
||||
unsigned short *outptr = dest->data;
|
||||
const LICE_pixel *p = fr->getBits();
|
||||
int span = fr->getRowSpan();
|
||||
if (fr->isFlipped())
|
||||
{
|
||||
p+=(fr->getHeight()-1)*span;
|
||||
span=-span;
|
||||
}
|
||||
int h = fr->getHeight(),w=fr->getWidth();
|
||||
while (h--)
|
||||
{
|
||||
int x=w;
|
||||
const LICE_pixel *sp = p;
|
||||
while (x--)
|
||||
{
|
||||
LICE_pixel pix = *sp++;
|
||||
*outptr++ = (((int)LICE_GETR(pix)&0xF8)>>3) | (((int)LICE_GETG(pix)&0xFC)<<3) | (((int)LICE_GETB(pix)&0xF8)<<8);
|
||||
}
|
||||
p += span;
|
||||
}
|
||||
}
|
||||
|
||||
void LICECaptureCompressor::DeflateBlock(void *data, int data_size, bool flush)
|
||||
{
|
||||
m_current_block_srcsize += data_size;
|
||||
m_inbytes += data_size;
|
||||
int bytesout=0;
|
||||
|
||||
m_compstream.next_in = (unsigned char *)data;
|
||||
m_compstream.avail_in = data_size;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int add_sz = data_size+32768;
|
||||
m_compstream.next_out = (unsigned char *)m_current_block.Add(NULL,add_sz);
|
||||
m_compstream.avail_out = add_sz;
|
||||
|
||||
int e = deflate(&m_compstream,flush?Z_FULL_FLUSH:Z_NO_FLUSH);
|
||||
|
||||
m_current_block.Add(NULL,-(int)m_compstream.avail_out);
|
||||
|
||||
bytesout+=add_sz-m_compstream.avail_out;
|
||||
|
||||
|
||||
if (e != Z_OK)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!m_compstream.avail_in && (!flush || add_sz==(int)m_compstream.avail_out)) break;
|
||||
}
|
||||
m_outsize += bytesout;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
LICECaptureCompressor::~LICECaptureCompressor()
|
||||
{
|
||||
// process any pending frames
|
||||
if (m_file)
|
||||
{
|
||||
OnFrame(NULL,0);
|
||||
deflateEnd(&m_compstream);
|
||||
}
|
||||
|
||||
delete m_file;
|
||||
m_framelists[0].Empty(true);
|
||||
m_framelists[1].Empty(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////
|
||||
///////DECOMPRESS
|
||||
//////////////////////////////////////////
|
||||
|
||||
|
||||
LICECaptureDecompressor::LICECaptureDecompressor(const char *fn, bool want_seekable) : m_workbm(0,0,1)
|
||||
{
|
||||
m_bytes_read=0;
|
||||
m_file_length_ms=0;
|
||||
m_rd_which=0;
|
||||
m_frameidx=0;
|
||||
memset(&m_compstream,0,sizeof(m_compstream));
|
||||
memset(&m_curhdr,0,sizeof(m_curhdr));
|
||||
m_file = new WDL_FileRead(fn,2,1024*1024);
|
||||
if (m_file->IsOpen())
|
||||
{
|
||||
if (inflateInit(&m_compstream)!=Z_OK)
|
||||
{
|
||||
delete m_file;
|
||||
m_file=0;
|
||||
}
|
||||
if (m_file)
|
||||
{
|
||||
m_file_frame_info.Clear();
|
||||
m_file_length_ms=0;
|
||||
if (want_seekable)
|
||||
{
|
||||
unsigned int lastpos = 0;
|
||||
int first_frame_delay = 0;
|
||||
while (ReadHdr(0))
|
||||
{
|
||||
m_file_frame_info.Add(&lastpos,1);
|
||||
unsigned int mst = m_file_length_ms;
|
||||
if (m_frame_deltas[0].GetSize())
|
||||
{
|
||||
if (lastpos > 0)
|
||||
mst += m_frame_deltas[0].Get()[0]-first_frame_delay; // TOC is by time of first frames, ignore first delay when seeking
|
||||
else
|
||||
first_frame_delay = m_frame_deltas[0].Get()[0];
|
||||
}
|
||||
m_file_frame_info.Add(&mst,1);
|
||||
|
||||
int x;
|
||||
for(x=0;x<m_frame_deltas[0].GetSize();x++)
|
||||
{
|
||||
m_file_length_ms+=m_frame_deltas[0].Get()[x];
|
||||
}
|
||||
|
||||
m_file->SetPosition(lastpos = (unsigned int)(m_file->GetPosition() + m_curhdr[0].cdata_left));
|
||||
}
|
||||
}
|
||||
|
||||
Seek(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_curhdr[m_rd_which].bpp!=16)
|
||||
{
|
||||
delete m_file;
|
||||
m_file=0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LICECaptureDecompressor::~LICECaptureDecompressor()
|
||||
{
|
||||
inflateEnd(&m_compstream);
|
||||
delete m_file;
|
||||
}
|
||||
|
||||
bool LICECaptureDecompressor::NextFrame() // TRUE if out of frames
|
||||
{
|
||||
if (++m_frameidx >= m_frame_deltas[m_rd_which].GetSize())
|
||||
{
|
||||
m_rd_which=!m_rd_which;
|
||||
|
||||
DecompressBlock(m_rd_which,1.0);
|
||||
if (!ReadHdr(!m_rd_which))
|
||||
memset(&m_curhdr[!m_rd_which],0,sizeof(m_curhdr[!m_rd_which]));
|
||||
m_frameidx=0;
|
||||
if (!m_curhdr[m_rd_which].bpp) return false;
|
||||
DecodeSlices();
|
||||
}
|
||||
else
|
||||
DecompressBlock(!m_rd_which,m_frameidx/(double)m_frame_deltas[m_rd_which].GetSize());
|
||||
return false;
|
||||
}
|
||||
|
||||
int LICECaptureDecompressor::Seek(unsigned int offset_ms)
|
||||
{
|
||||
|
||||
memset(m_curhdr,0,sizeof(m_curhdr));
|
||||
if (!m_file) return -1;
|
||||
|
||||
int rval=0;
|
||||
|
||||
unsigned int seekpos=0;
|
||||
m_frameidx=0;
|
||||
if (offset_ms>0&&m_file_frame_info.GetSize())
|
||||
{
|
||||
int x;
|
||||
for(x=0;x<m_file_frame_info.GetSize()-2;x+=2)
|
||||
{
|
||||
if (offset_ms < m_file_frame_info.Get()[x+2+1]) break;
|
||||
}
|
||||
seekpos = m_file_frame_info.Get()[x];
|
||||
offset_ms -= m_file_frame_info.Get()[x+1];
|
||||
// figure out the best place to seek
|
||||
}
|
||||
else
|
||||
{
|
||||
if (offset_ms>0) rval=-1;
|
||||
offset_ms=0;
|
||||
}
|
||||
|
||||
m_rd_which=0;
|
||||
m_file->SetPosition(seekpos);
|
||||
if (!ReadHdr(m_rd_which)||!DecompressBlock(m_rd_which,1.0))
|
||||
{
|
||||
rval=-1;
|
||||
memset(&m_curhdr,0,sizeof(m_curhdr));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (offset_ms>0 && rval==0)
|
||||
{
|
||||
int x;
|
||||
for (x = 1; x < m_frame_deltas[m_rd_which].GetSize(); x++)
|
||||
{
|
||||
if (offset_ms < m_frame_deltas[m_rd_which].Get()[x])
|
||||
{
|
||||
rval = offset_ms;
|
||||
break;
|
||||
}
|
||||
offset_ms -= m_frame_deltas[m_rd_which].Get()[x];
|
||||
}
|
||||
m_frameidx=x-1;
|
||||
}
|
||||
if (!ReadHdr(!m_rd_which))
|
||||
memset(&m_curhdr[!m_rd_which],0,sizeof(m_curhdr[!m_rd_which]));
|
||||
|
||||
DecodeSlices();
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
bool LICECaptureDecompressor::ReadHdr(int whdr) // todo: eventually make this read/decompress the next header as it goes
|
||||
{
|
||||
m_tmp.Clear();
|
||||
int hdr_sz = (4*9);
|
||||
if (m_file->Read(m_tmp.Add(NULL,hdr_sz),hdr_sz)!=hdr_sz) return false;
|
||||
m_bytes_read+=hdr_sz;
|
||||
int ver=0;
|
||||
m_tmp.GetTFromLE(&ver);
|
||||
if (ver !=LCF_VERSION) return false;
|
||||
m_tmp.GetTFromLE(&m_curhdr[whdr].bpp);
|
||||
m_tmp.GetTFromLE(&m_curhdr[whdr].w);
|
||||
m_tmp.GetTFromLE(&m_curhdr[whdr].h);
|
||||
m_tmp.GetTFromLE(&m_curhdr[whdr].bsize_w);
|
||||
m_tmp.GetTFromLE(&m_curhdr[whdr].bsize_h);
|
||||
int nf=0;
|
||||
m_tmp.GetTFromLE(&nf);
|
||||
int csize=0;
|
||||
m_tmp.GetTFromLE(&csize);
|
||||
|
||||
int dsize=0;
|
||||
m_tmp.GetTFromLE(&dsize);
|
||||
|
||||
if (nf<1 || nf > 1024) return false;
|
||||
|
||||
m_frame_deltas[whdr].Resize(nf);
|
||||
|
||||
if (m_frame_deltas[whdr].GetSize()!=nf) return false;
|
||||
|
||||
if (m_file->Read(m_frame_deltas[whdr].Get(),nf*4)!=nf*4) return false;
|
||||
m_bytes_read+=nf*4;
|
||||
int x;
|
||||
for(x=0;x<nf;x++)
|
||||
{
|
||||
WDL_Queue::WDL_Queue__bswap_buffer(m_frame_deltas[whdr].Get()+x,4);
|
||||
}
|
||||
m_curhdr[whdr].cdata_left = csize;
|
||||
|
||||
inflateReset(&m_compstream);
|
||||
m_compstream.avail_out = dsize;
|
||||
m_compstream.next_out = (unsigned char *)m_decompdata[whdr].Resize(dsize,false);
|
||||
if (m_decompdata[whdr].GetSize()!=dsize) return false;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LICECaptureDecompressor::DecompressBlock(int whdr, double percent)
|
||||
{
|
||||
if (m_compstream.avail_out)
|
||||
{
|
||||
unsigned char buf[16384];
|
||||
for (;;)
|
||||
{
|
||||
if (percent<1.0&&m_decompdata[whdr].GetSize())
|
||||
{
|
||||
double p = ((m_decompdata[whdr].GetSize()-m_compstream.avail_out)/(double)m_decompdata[whdr].GetSize());
|
||||
if (p>percent) break;
|
||||
}
|
||||
m_compstream.next_in = buf;
|
||||
m_compstream.avail_in = m_curhdr[whdr].cdata_left;
|
||||
if (m_compstream.avail_in > (int)sizeof(buf)) m_compstream.avail_in=(int)sizeof(buf);
|
||||
|
||||
m_compstream.avail_in = m_file->Read(buf,m_compstream.avail_in);
|
||||
m_bytes_read+=m_compstream.avail_in;
|
||||
m_curhdr[whdr].cdata_left -= m_compstream.avail_in;
|
||||
|
||||
int e = inflate(&m_compstream,0);
|
||||
if (e != Z_OK&&e!=Z_STREAM_END)
|
||||
{
|
||||
// printf("inflate error: %d (%d/%d)\n",e,m_compstream.avail_in, m_curhdr[whdr].cdata_left);
|
||||
return !m_compstream.avail_out;
|
||||
}
|
||||
if (!m_compstream.avail_out && !m_compstream.avail_in) break;
|
||||
}
|
||||
m_compstream.next_in = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int LICECaptureDecompressor::GetTimeToNextFrame()
|
||||
{
|
||||
int nf = m_frame_deltas[m_rd_which].GetSize();
|
||||
int fidx = m_frameidx;
|
||||
|
||||
if (fidx<0&& nf) return m_frame_deltas[m_rd_which].Get()[0];
|
||||
|
||||
if (fidx+1 < nf) return m_frame_deltas[m_rd_which].Get()[fidx+1];
|
||||
|
||||
if (m_curhdr[!m_rd_which].bpp && m_frame_deltas[!m_rd_which].GetSize())
|
||||
return m_frame_deltas[!m_rd_which].Get()[0];
|
||||
|
||||
return 100;
|
||||
}
|
||||
|
||||
void LICECaptureDecompressor::DecodeSlices()
|
||||
{
|
||||
int nf = m_frame_deltas[m_rd_which].GetSize();
|
||||
unsigned char *sp = (unsigned char *)m_decompdata[m_rd_which].Get();
|
||||
int sp_left = m_decompdata[m_rd_which].GetSize();
|
||||
hdrType *hdr = m_curhdr+m_rd_which;
|
||||
int ns_x = (hdr->w + hdr->bsize_w-1)/hdr->bsize_w;
|
||||
int ns_y = (hdr->h + hdr->bsize_h-1)/hdr->bsize_h;
|
||||
|
||||
int ns_frame = ns_x*ns_y;
|
||||
void **slicelist = m_slices.Resize(nf * ns_frame);
|
||||
|
||||
// format of sp is:
|
||||
// nf slices
|
||||
// each slice is :
|
||||
// initial value
|
||||
// repeat cnt
|
||||
// frame
|
||||
// repeat cnt
|
||||
// ..
|
||||
|
||||
int ypos,
|
||||
toth=hdr->h,
|
||||
totw=hdr->w;
|
||||
|
||||
int bytespersample = (hdr->bpp+7)/8;
|
||||
|
||||
for (ypos = 0; ypos < toth; ypos+=hdr->bsize_h)
|
||||
{
|
||||
int hei = toth-ypos;
|
||||
if (hei>hdr->bsize_h) hei=hdr->bsize_h;
|
||||
int xpos;
|
||||
for (xpos=0; xpos<totw; xpos+=hdr->bsize_w)
|
||||
{
|
||||
int wid = totw-xpos;
|
||||
if (wid>hdr->bsize_w) wid=hdr->bsize_w;
|
||||
|
||||
int sz1=wid*hei*bytespersample;
|
||||
|
||||
int slicewritepos = 0,i = 0;
|
||||
void *lvalid = NULL;
|
||||
while (i<nf&&sp_left>0)
|
||||
{
|
||||
if (lvalid)
|
||||
{
|
||||
unsigned char c = *sp++;
|
||||
sp_left--;
|
||||
while (c-->0 && i++ < nf)
|
||||
{
|
||||
// repeat last slice
|
||||
slicelist[slicewritepos] = lvalid;
|
||||
slicewritepos += ns_frame;
|
||||
}
|
||||
}
|
||||
if (i<nf)
|
||||
{
|
||||
lvalid = slicelist[slicewritepos] = sp;
|
||||
slicewritepos += ns_frame;
|
||||
sp += sz1;
|
||||
sp_left -= sz1;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if( sp_left < 0)
|
||||
{
|
||||
m_slices.Resize(0);
|
||||
return;
|
||||
}
|
||||
|
||||
slicelist++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LICE_IBitmap *LICECaptureDecompressor::GetCurrentFrame()
|
||||
{
|
||||
int nf = m_frame_deltas[m_rd_which].GetSize();
|
||||
int fidx = m_frameidx;
|
||||
hdrType *hdr = m_curhdr+m_rd_which;
|
||||
if (fidx >=0 && fidx < nf && m_slices.GetSize() && hdr->bsize_w && hdr->bsize_h)
|
||||
{
|
||||
int ns_x = (hdr->w + hdr->bsize_w-1)/hdr->bsize_w;
|
||||
int ns_y = (hdr->h + hdr->bsize_h-1)/hdr->bsize_h;
|
||||
|
||||
int ns_frame = ns_x*ns_y;
|
||||
|
||||
if (m_slices.GetSize() != ns_frame*nf)
|
||||
return NULL; // invalid slices
|
||||
|
||||
if (hdr->bpp == 16)
|
||||
{
|
||||
m_workbm.resize(hdr->w,hdr->h);
|
||||
//unsigned short *
|
||||
// format of m_decompdata is:
|
||||
// nf frames of slice1, nf frames of slice2, etc
|
||||
|
||||
LICE_pixel *pout = m_workbm.getBits();
|
||||
int span = m_workbm.getRowSpan();
|
||||
|
||||
int ypos,
|
||||
toth=hdr->h,
|
||||
totw=hdr->w;
|
||||
void **sliceptr = m_slices.Get() + ns_frame * fidx;
|
||||
|
||||
for (ypos = 0; ypos < toth; ypos+=hdr->bsize_h)
|
||||
{
|
||||
int hei = toth-ypos;
|
||||
if (hei>hdr->bsize_h) hei=hdr->bsize_h;
|
||||
int xpos;
|
||||
for (xpos=0; xpos<totw; xpos+=hdr->bsize_w)
|
||||
{
|
||||
int wid = totw-xpos;
|
||||
if (wid>hdr->bsize_w) wid=hdr->bsize_w;
|
||||
|
||||
unsigned short *rdptr = (unsigned short *)*sliceptr;
|
||||
|
||||
sliceptr++;
|
||||
|
||||
LICE_pixel *dest = pout + xpos + ypos*span;
|
||||
int y;
|
||||
for (y=0;y<hei;y++)
|
||||
{
|
||||
int x=wid;
|
||||
LICE_pixel *wr = dest;
|
||||
while (x--)
|
||||
{
|
||||
unsigned short px = *rdptr++;
|
||||
*wr++ = LICE_RGBA((px<<3)&0xF8,(px>>3)&0xFC,(px>>8)&0xF8,255);
|
||||
}
|
||||
dest+=span;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return &m_workbm;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
111
oversampling/WDL/lice/lice_lcf.h
Normal file
111
oversampling/WDL/lice/lice_lcf.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#ifndef _LICE_LCF_H_
|
||||
#define _LICE_LCF_H_
|
||||
|
||||
#include "../zlib/zlib.h"
|
||||
#include "lice.h"
|
||||
|
||||
#include "../ptrlist.h"
|
||||
#include "../queue.h"
|
||||
class WDL_FileWrite;
|
||||
class WDL_FileRead;
|
||||
|
||||
class LICECaptureCompressor
|
||||
{
|
||||
public:
|
||||
LICECaptureCompressor(const char *outfn, int w, int h, int interval=20, int bsize_w=128, int bsize_h=16);
|
||||
|
||||
~LICECaptureCompressor();
|
||||
|
||||
bool IsOpen() { return !!m_file; }
|
||||
void OnFrame(LICE_IBitmap *fr, int delta_t_ms);
|
||||
|
||||
WDL_INT64 GetOutSize() { return m_outsize; }
|
||||
WDL_INT64 GetInSize() { return m_inbytes; }
|
||||
|
||||
private:
|
||||
WDL_FileWrite *m_file;
|
||||
WDL_INT64 m_outsize,m_inbytes;
|
||||
int m_inframes, m_outframes;
|
||||
|
||||
int m_w,m_h,m_interval,m_bsize_w,m_bsize_h;
|
||||
|
||||
|
||||
struct frameRec
|
||||
{
|
||||
frameRec(int sz) { data=(unsigned short *)malloc(sz*sizeof(short)); delta_t_ms=0; }
|
||||
~frameRec() { free(data); }
|
||||
unsigned short *data; // shorts
|
||||
int delta_t_ms; // time (ms) since last frame
|
||||
};
|
||||
WDL_PtrList<frameRec> m_framelists[2];
|
||||
WDL_Queue m_current_block;
|
||||
WDL_Queue m_hdrqueue;
|
||||
|
||||
int m_state, m_which,m_outchunkpos,m_numrows,m_numcols;
|
||||
int m_current_block_srcsize;
|
||||
|
||||
z_stream m_compstream;
|
||||
|
||||
void BitmapToFrameRec(LICE_IBitmap *fr, frameRec *dest);
|
||||
void DeflateBlock(void *data, int data_size, bool flush);
|
||||
void AddHdrInt(int a) { m_hdrqueue.AddToLE(&a); }
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
class LICECaptureDecompressor
|
||||
{
|
||||
public:
|
||||
LICECaptureDecompressor(const char *fn, bool want_seekable=false);
|
||||
~LICECaptureDecompressor();
|
||||
|
||||
|
||||
bool IsOpen() { return !!m_file; }
|
||||
|
||||
// only supported if want_seekable=true
|
||||
int GetLength() { return m_file_length_ms; } // length in ms
|
||||
int Seek(unsigned int offset_ms); // return -1 on fail (out of range), or >0 to tell you how far into the frame you seeked (0=exact hit)
|
||||
|
||||
bool NextFrame(); // TRUE if out of frames
|
||||
LICE_IBitmap *GetCurrentFrame(); // can return NULL if error
|
||||
int GetTimeToNextFrame(); // delta in ms
|
||||
|
||||
int GetWidth(){ return m_curhdr[m_rd_which].w; }
|
||||
int GetHeight(){ return m_curhdr[m_rd_which].h; }
|
||||
|
||||
int m_bytes_read; // increases for statistics, caller can clear
|
||||
|
||||
private:
|
||||
LICE_MemBitmap m_workbm;
|
||||
|
||||
struct hdrType
|
||||
{
|
||||
int bpp;
|
||||
int w, h;
|
||||
int bsize_w, bsize_h;
|
||||
int cdata_left;
|
||||
} m_curhdr[2];
|
||||
|
||||
int m_rd_which;
|
||||
int m_frameidx;
|
||||
|
||||
bool ReadHdr(int whdr);
|
||||
bool DecompressBlock(int whdr, double percent=1.0);
|
||||
|
||||
z_stream m_compstream;
|
||||
WDL_Queue m_tmp;
|
||||
|
||||
WDL_FileRead *m_file;
|
||||
|
||||
unsigned int m_file_length_ms;
|
||||
WDL_TypedQueue<unsigned int> m_file_frame_info; //pairs of offset_bytes, offset_ms
|
||||
|
||||
WDL_TypedBuf<int> m_frame_deltas[2];
|
||||
WDL_HeapBuf m_decompdata[2];
|
||||
WDL_TypedBuf<void *> m_slices; // indexed by [frame][slice]
|
||||
|
||||
void DecodeSlices();
|
||||
};
|
||||
|
||||
#endif
|
||||
2035
oversampling/WDL/lice/lice_line.cpp
Normal file
2035
oversampling/WDL/lice/lice_line.cpp
Normal file
File diff suppressed because it is too large
Load Diff
625
oversampling/WDL/lice/lice_lvg.cpp
Normal file
625
oversampling/WDL/lice/lice_lvg.cpp
Normal file
@@ -0,0 +1,625 @@
|
||||
#ifndef WDL_NO_DEFINE_MINMAX
|
||||
#define WDL_NO_DEFINE_MINMAX
|
||||
#endif
|
||||
#include "lice.h"
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "../projectcontext.h"
|
||||
#include "../lineparse.h"
|
||||
#include "../ptrlist.h"
|
||||
#include "../assocarray.h"
|
||||
|
||||
#define PI 3.1415926535897932384626433832795
|
||||
|
||||
static inline int chartohex(char c)
|
||||
{
|
||||
if (c >= '0' && c<='9') return c-'0';
|
||||
else if (c>='A' && c<='F') return 10 + c - 'A';
|
||||
else if (c>='a' && c<='f') return 10 + c - 'a';
|
||||
return -1;
|
||||
}
|
||||
static int __boolval(const char *p, int defval)
|
||||
{
|
||||
if (!stricmp(p,"yes") ||
|
||||
!stricmp(p,"true") ||
|
||||
!stricmp(p,"on") ||
|
||||
atoi(p)>0) return 1;
|
||||
if (!stricmp(p,"no") ||
|
||||
!stricmp(p,"false") ||
|
||||
!stricmp(p,"off") ||
|
||||
!stricmp(p,"0")) return 0;
|
||||
return defval;
|
||||
}
|
||||
|
||||
static LICE_pixel __colorval(const char *p, LICE_pixel def)
|
||||
{
|
||||
const size_t lp = strlen(p);
|
||||
if (lp == 3)
|
||||
{
|
||||
int r = chartohex(p[0]);
|
||||
int g = chartohex(p[1]);
|
||||
int b = chartohex(p[2]);
|
||||
if (r>=0&&g>=0&&b>=0)
|
||||
def = LICE_RGBA(r+(r<<4),g+(g<<4),b+(b<<4),255);
|
||||
}
|
||||
else if (lp == 6||lp==8)
|
||||
{
|
||||
int r = chartohex(p[0]), r2 = chartohex(p[1]);
|
||||
int g = chartohex(p[2]), g2 = chartohex(p[3]);
|
||||
int b = chartohex(p[4]), b2 = chartohex(p[5]);
|
||||
int a = 0xf, a2=0xf;
|
||||
if (lp==8) { a=chartohex(p[6]); a2=chartohex(p[7]); }
|
||||
if (r>=0&&g>=0&&b>=0&&r2>=0&&g2>=0&&b2>=0&&a>=0&&a2>=0)
|
||||
def = LICE_RGBA((r<<4)+r2,(g<<4)+g2,(b<<4)+b2,(a<<4)+a2);
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
class lvgRenderState
|
||||
{
|
||||
public:
|
||||
lvgRenderState()
|
||||
{
|
||||
m_color=LICE_RGBA(255,255,255,255);
|
||||
m_alpha=1.0f;
|
||||
m_blend = LICE_BLIT_MODE_COPY;
|
||||
m_aa = false;
|
||||
}
|
||||
~lvgRenderState() { }
|
||||
|
||||
LICE_pixel m_color;
|
||||
float m_alpha;
|
||||
int m_blend;
|
||||
bool m_aa;
|
||||
|
||||
WDL_TypedBuf<bool> m_aa_stack;
|
||||
WDL_TypedBuf<float> m_alpha_stack;
|
||||
WDL_TypedBuf<LICE_pixel> m_color_stack;
|
||||
WDL_TypedBuf<int> m_blend_stack;
|
||||
|
||||
/////////
|
||||
|
||||
void parsealpha(const char *p)
|
||||
{
|
||||
int idx=0;
|
||||
if (*p == '-') idx++;
|
||||
if (p[idx] == '.' || (p[idx] >= '0' && p[idx] <= '9'))
|
||||
m_alpha = (float)atof(p);
|
||||
}
|
||||
|
||||
void parseaa(const char *p)
|
||||
{
|
||||
int a = __boolval(p,-1);
|
||||
if (a>=0) m_aa = !!a;
|
||||
}
|
||||
|
||||
void parseblend(const char *p)
|
||||
{
|
||||
if (!stricmp(p,"copy")) m_blend = LICE_BLIT_MODE_COPY;
|
||||
else if (!stricmp(p,"add")) m_blend = LICE_BLIT_MODE_ADD;
|
||||
else if (!stricmp(p,"dodge")) m_blend = LICE_BLIT_MODE_DODGE;
|
||||
else if (!stricmp(p,"mul")||!stricmp(p,"multiply")) m_blend = LICE_BLIT_MODE_MUL;
|
||||
else if (!stricmp(p,"overlay")) m_blend = LICE_BLIT_MODE_MUL;
|
||||
else if (!stricmp(p,"hsvadj")) m_blend = LICE_BLIT_MODE_HSVADJ;
|
||||
}
|
||||
|
||||
void parsecolor(const char *p)
|
||||
{
|
||||
m_color = __colorval(p,m_color);
|
||||
}
|
||||
|
||||
#define DEF_PUSHPOP(name,defpopval) \
|
||||
void push##name() { int sz=m_##name##_stack.GetSize(); m_##name##_stack.Resize(sz+1,false)[sz] = m_##name; } \
|
||||
void pop##name() { int sz = m_##name##_stack.GetSize()-1; m_##name = sz>=0 ? m_##name##_stack.Get()[sz] : defpopval; m_##name##_stack.Resize(sz,false); }
|
||||
DEF_PUSHPOP(color,LICE_RGBA(0,0,0,255))
|
||||
DEF_PUSHPOP(alpha,1.0f)
|
||||
DEF_PUSHPOP(aa,false)
|
||||
DEF_PUSHPOP(blend,LICE_BLIT_MODE_COPY)
|
||||
#undef DEF_PUSHPOP
|
||||
|
||||
bool processAttributeLine(LineParser *lp)
|
||||
{
|
||||
int i,numtok=lp->getnumtokens();
|
||||
switch (lp->gettoken_enum(0,"color\0"
|
||||
"alpha\0"
|
||||
"aa\0"
|
||||
"blend\0"
|
||||
"\0"))
|
||||
{
|
||||
#define PROCTYPE(v,name) \
|
||||
case v: for (i=1;i<numtok;i++) { \
|
||||
const char *p = lp->gettoken_str(i); \
|
||||
if (!stricmp(p,"push")) push##name(); \
|
||||
else if (!stricmp(p,"pop")) pop##name(); \
|
||||
else parse##name(p); \
|
||||
} \
|
||||
return true;
|
||||
|
||||
PROCTYPE(0,color)
|
||||
PROCTYPE(1,alpha)
|
||||
PROCTYPE(2,aa)
|
||||
PROCTYPE(3,blend)
|
||||
#undef PROCTYPE
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
class lvgImageCtx
|
||||
{
|
||||
public:
|
||||
lvgImageCtx(lvgImageCtx *par) : m_images(true,deleteThis)
|
||||
{
|
||||
m_in_render=false;
|
||||
m_par=par;
|
||||
m_cachedImage=0;
|
||||
m_base_w=0;
|
||||
m_base_h=0;
|
||||
}
|
||||
~lvgImageCtx()
|
||||
{
|
||||
delete m_cachedImage;
|
||||
m_lines.Empty(true,free);
|
||||
}
|
||||
|
||||
WDL_PtrList<char> m_lines;
|
||||
LICE_IBitmap *m_cachedImage;
|
||||
|
||||
lvgImageCtx *m_par;
|
||||
WDL_StringKeyedArray<lvgImageCtx *> m_images;
|
||||
|
||||
int m_base_w,m_base_h;
|
||||
bool m_in_render;
|
||||
|
||||
void render(lvgRenderState *rstate, int wantw, int wanth);
|
||||
|
||||
private:
|
||||
static void deleteThis(lvgImageCtx *t) { delete t; }
|
||||
|
||||
double parsecoord(const char *p, double scale, bool round)
|
||||
{
|
||||
if (!*p) return 0;
|
||||
if (p[0] == 'a' && p[1]) return atoi(p+1);
|
||||
if (p[0] == 'w')
|
||||
{
|
||||
scale = m_cachedImage ? m_cachedImage->getWidth() : 0.0;
|
||||
p++;
|
||||
}
|
||||
else if (p[0] == 'h')
|
||||
{
|
||||
scale = m_cachedImage ? m_cachedImage->getHeight() : 0.0;
|
||||
p++;
|
||||
}
|
||||
return atof(p) * scale + (round ? 0.5 : 0.0);
|
||||
}
|
||||
void processLvgLine(LineParser *lp, lvgRenderState *state, LICE_IBitmap *bm, double xscale, double yscale);
|
||||
|
||||
};
|
||||
|
||||
#define DECL_OPT(type, cfunc) \
|
||||
static type getoption_##type(LineParser *lp, int startidx, const char *name, type def) { \
|
||||
const size_t namelen = strlen(name); \
|
||||
for(;startidx<lp->getnumtokens();startidx++) { \
|
||||
const char *p=lp->gettoken_str(startidx); \
|
||||
if (!strnicmp(name,p,namelen) && p[namelen]=='=') return cfunc(p+namelen+1,def); \
|
||||
} \
|
||||
return def; \
|
||||
}
|
||||
|
||||
static int __intval(const char *p, int def) { return atoi(p); }
|
||||
static double __dblval(const char *p, double def) { return atof(p); }
|
||||
|
||||
DECL_OPT(bool,!!__boolval)
|
||||
DECL_OPT(int,__intval)
|
||||
DECL_OPT(double,__dblval)
|
||||
DECL_OPT(LICE_pixel,__colorval)
|
||||
|
||||
#undef DECL_OPT
|
||||
|
||||
void lvgImageCtx::processLvgLine(LineParser *lp, lvgRenderState *state, LICE_IBitmap *bm, double xscale, double yscale)
|
||||
{
|
||||
if (state->processAttributeLine(lp)) return;
|
||||
|
||||
int numtok = lp->getnumtokens();
|
||||
const char *tok = lp->gettoken_str(0);
|
||||
if (!stricmp(tok,"line"))
|
||||
{
|
||||
int i;
|
||||
float lx,ly;
|
||||
for (i = 1; i < numtok-1; i+= 2)
|
||||
{
|
||||
const char *p=lp->gettoken_str(i);
|
||||
if (strstr(p,"=")) break;
|
||||
float x=(float)parsecoord(p,xscale,false);
|
||||
p=lp->gettoken_str(i+1);
|
||||
if (strstr(p,"=")) break;
|
||||
float y=(float)parsecoord(p,yscale,false);
|
||||
|
||||
if (i!=1) LICE_FLine(bm,lx,ly,x,y,state->m_color,state->m_alpha,state->m_blend,state->m_aa);
|
||||
|
||||
lx=x;
|
||||
ly=y;
|
||||
}
|
||||
}
|
||||
else if (!stricmp(tok,"circle"))
|
||||
{
|
||||
if (numtok>=4)
|
||||
{
|
||||
float x=(float)parsecoord(lp->gettoken_str(1),xscale,false);
|
||||
float y=(float)parsecoord(lp->gettoken_str(2),yscale,false);
|
||||
float r=(float)(atof(lp->gettoken_str(3))*lice_min(xscale,yscale));
|
||||
if (getoption_bool(lp,1,"fill",false))
|
||||
{
|
||||
LICE_FillCircle(bm,x,y,r,state->m_color,state->m_alpha,state->m_blend,state->m_aa);
|
||||
}
|
||||
else
|
||||
LICE_Circle(bm,x,y,r,state->m_color,state->m_alpha,state->m_blend,state->m_aa);
|
||||
}
|
||||
}
|
||||
else if (!stricmp(tok,"arc"))
|
||||
{
|
||||
if (numtok>=6)
|
||||
{
|
||||
float x=(float)parsecoord(lp->gettoken_str(1),xscale,false);
|
||||
float y=(float)parsecoord(lp->gettoken_str(2),yscale,false);
|
||||
float r=(float)(atof(lp->gettoken_str(3))*lice_min(xscale,yscale));
|
||||
float a1=(float)(atof(lp->gettoken_str(4))*PI/180.0);
|
||||
float a2=(float)(atof(lp->gettoken_str(5))*PI/180.0);
|
||||
LICE_Arc(bm,x,y,r,a1,a2,state->m_color,state->m_alpha,state->m_blend,state->m_aa);
|
||||
}
|
||||
}
|
||||
else if (!stricmp(tok,"fill"))
|
||||
{
|
||||
if (numtok>=3) // fill x y [cmask=xxxxxx kmask=xxxxxxx]
|
||||
{
|
||||
LICE_pixel cmask = getoption_LICE_pixel(lp,1,"cmask",LICE_RGBA(255,255,255,0));
|
||||
LICE_pixel kmask = getoption_LICE_pixel(lp,1,"kmask",LICE_RGBA(0,0,0,0));
|
||||
int x = (int)parsecoord(lp->gettoken_str(1),xscale,true);
|
||||
int y = (int)parsecoord(lp->gettoken_str(2),yscale,true);
|
||||
|
||||
LICE_SimpleFill(bm,x,y,state->m_color,cmask,kmask);
|
||||
}
|
||||
}
|
||||
else if (!stricmp(tok,"rect"))
|
||||
{
|
||||
if (numtok>=5) // rect x y w h [dcdx=xxxxxxxx dcdy=xxxxxxxxx dcdxscale=1.0 dcdyscale=1.0]
|
||||
{
|
||||
LICE_pixel dcdx = getoption_LICE_pixel(lp,1,"dcdx",LICE_RGBA(0x80,0x80,0x80,0x80));
|
||||
LICE_pixel dcdy = getoption_LICE_pixel(lp,1,"dcdy",LICE_RGBA(0x80,0x80,0x80,0x80));
|
||||
double dcdxsc = getoption_double(lp,1,"dcdxscale",1.0);
|
||||
double dcdysc = getoption_double(lp,1,"dcdyscale",1.0);
|
||||
|
||||
// todo: any options?
|
||||
int x = (int)parsecoord(lp->gettoken_str(1),xscale,true);
|
||||
int y = (int)parsecoord(lp->gettoken_str(2),yscale,true);
|
||||
int w = (int)parsecoord(lp->gettoken_str(3),xscale,true);
|
||||
int h = (int)parsecoord(lp->gettoken_str(4),yscale,true);
|
||||
if (w>0 && h>0)
|
||||
{
|
||||
if (dcdx!=LICE_RGBA(0x80,0x80,0x80,0x80) ||
|
||||
dcdy!=LICE_RGBA(0x80,0x80,0x80,0x80))
|
||||
{
|
||||
LICE_pixel sc = state->m_color;
|
||||
dcdxsc /= w*128.0;
|
||||
dcdysc /= h*128.0;
|
||||
LICE_GradRect(bm,x,y,w,h,
|
||||
(float)(LICE_GETR(sc)/255.0),
|
||||
(float)(LICE_GETG(sc)/255.0),
|
||||
(float)(LICE_GETB(sc)/255.0),
|
||||
(float)(LICE_GETA(sc)/255.0*state->m_alpha),
|
||||
(float)(((int)LICE_GETR(dcdx)-0x80)*dcdxsc),
|
||||
(float)(((int)LICE_GETG(dcdx)-0x80)*dcdxsc),
|
||||
(float)(((int)LICE_GETB(dcdx)-0x80)*dcdxsc),
|
||||
(float)(((int)LICE_GETA(dcdx)-0x80)*dcdxsc),
|
||||
(float)(((int)LICE_GETR(dcdy)-0x80)*dcdysc),
|
||||
(float)(((int)LICE_GETG(dcdy)-0x80)*dcdysc),
|
||||
(float)(((int)LICE_GETB(dcdy)-0x80)*dcdysc),
|
||||
(float)(((int)LICE_GETA(dcdy)-0x80)*dcdysc),
|
||||
state->m_blend);
|
||||
}
|
||||
else
|
||||
LICE_FillRect(bm,x,y,w,h,state->m_color,state->m_alpha,state->m_blend);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!stricmp(tok,"rerender"))
|
||||
{
|
||||
if (numtok>=2)
|
||||
{
|
||||
int forcew=getoption_int(lp,1,"w",0),forceh=getoption_int(lp,1,"h",0);
|
||||
bool useState=getoption_bool(lp,1,"usestate",false);
|
||||
|
||||
lvgImageCtx *scan = this;
|
||||
while (scan)
|
||||
{
|
||||
lvgImageCtx *p = scan->m_images.Get(lp->gettoken_str(1));
|
||||
if (p)
|
||||
{
|
||||
if (!p->m_in_render)
|
||||
{
|
||||
p->m_in_render=true;
|
||||
p->render(useState ? state : NULL,forcew,forceh);
|
||||
p->m_in_render=false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
scan=scan->m_par;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!stricmp(tok,"blit"))
|
||||
{
|
||||
if (numtok>=3) // blit image x y [options]
|
||||
{
|
||||
LICE_IBitmap *src=NULL;
|
||||
lvgImageCtx *scan = this;
|
||||
const char *rd = lp->gettoken_str(1);
|
||||
|
||||
while (!strnicmp(rd,"parent:",7)) { scan = scan ? scan->m_par : NULL; rd += 7; }
|
||||
|
||||
if (!stricmp(rd,"parent"))
|
||||
{
|
||||
if (scan) scan=scan->m_par;
|
||||
if (scan) src=scan->m_cachedImage;
|
||||
}
|
||||
else if (!stricmp(rd,"self"))
|
||||
{
|
||||
if (scan) src=scan->m_cachedImage;
|
||||
}
|
||||
else while (scan&&!src)
|
||||
{
|
||||
lvgImageCtx *p = scan->m_images.Get(rd);
|
||||
if (p)
|
||||
{
|
||||
if (!p->m_cachedImage && !p->m_in_render)
|
||||
{
|
||||
p->m_in_render=true;
|
||||
p->render(NULL,0,0);
|
||||
p->m_in_render=false;
|
||||
}
|
||||
src = p->m_cachedImage;
|
||||
break;
|
||||
}
|
||||
scan=scan->m_par;
|
||||
}
|
||||
if (src)
|
||||
{
|
||||
int x = (int)parsecoord(lp->gettoken_str(2),xscale,true);
|
||||
int y = (int)parsecoord(lp->gettoken_str(3),yscale,true);
|
||||
|
||||
// these will be options filter= srcalpha= w= h= scale=
|
||||
bool filter=getoption_bool(lp,1,"filter",true);
|
||||
bool usesrcalpha = getoption_bool(lp,1,"srcalpha",true);
|
||||
int w = getoption_int(lp,1,"w",src->getWidth());
|
||||
int h = getoption_int(lp,1,"h",src->getHeight());
|
||||
double sc = getoption_double(lp,1,"scale",1.0f);
|
||||
if (fabs(sc-1.0)>0.0000000001)
|
||||
{
|
||||
w = (int)(w*sc+0.5);
|
||||
h = (int)(h*sc+0.5);
|
||||
}
|
||||
// double ang = getoption_double(lp,1,"rotate",0.0) * PI / 180.0;
|
||||
float sx=(float)getoption_double(lp,1,"srcx",0.0);
|
||||
float sy=(float)getoption_double(lp,1,"srcy",0.0);
|
||||
float sw=(float)getoption_double(lp,1,"srcw",src->getWidth());
|
||||
float sh=(float)getoption_double(lp,1,"srch",src->getHeight());
|
||||
// if (fabs(ang)>0.0001) LICE_RotatedBlit(bm,src,x,y,w,h,sx,sy,sw,sh,ang,true,state->m_alpha,state->m_blend,0,0);
|
||||
//else
|
||||
LICE_ScaledBlit(bm,src,x,y,w,h,sx,sy,sw,sh,
|
||||
state->m_alpha,state->m_blend|(filter ? LICE_BLIT_FILTER_BILINEAR : 0)|(usesrcalpha ? LICE_BLIT_USE_ALPHA : 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lvgImageCtx::render(lvgRenderState *rstate, int wantw, int wanth)
|
||||
{
|
||||
if (wantw<1) wantw = m_base_w;
|
||||
if (wanth<1) wanth = m_base_h;
|
||||
|
||||
if (wantw<1||wanth<1)
|
||||
{
|
||||
if (m_cachedImage) m_cachedImage->resize(0,0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_cachedImage) m_cachedImage = new LICE_MemBitmap(wantw,wanth);
|
||||
else m_cachedImage->resize(wantw,wanth);
|
||||
|
||||
LICE_Clear(m_cachedImage,LICE_RGBA(0,0,0,0));
|
||||
|
||||
lvgRenderState rs;
|
||||
if (rstate) rs = *rstate;
|
||||
|
||||
double xscale = wantw / lice_max(m_base_w,1);
|
||||
double yscale = wanth / lice_max(m_base_h,1);
|
||||
int x;
|
||||
bool comment_state=false;
|
||||
LineParser lp(comment_state);
|
||||
for (x=0;x<m_lines.GetSize();x++)
|
||||
{
|
||||
if (!lp.parse(m_lines.Get(x)) && lp.getnumtokens()>0)
|
||||
processLvgLine(&lp,&rs,m_cachedImage,xscale,yscale);
|
||||
}
|
||||
}
|
||||
|
||||
void *LICE_GetSubLVG(void *lvg, const char *subname)
|
||||
{
|
||||
if (!lvg||!subname||!*subname) return NULL;
|
||||
lvgImageCtx *t = (lvgImageCtx *)lvg;
|
||||
return t->m_images.Get(subname);
|
||||
}
|
||||
|
||||
LICE_IBitmap *LICE_RenderLVG(void *lvg, int reqw, int reqh, LICE_IBitmap *bmOut)
|
||||
{
|
||||
lvgImageCtx *t = (lvgImageCtx *)lvg;
|
||||
if (!t || !t->m_lines.GetSize() || t->m_in_render) return NULL;
|
||||
|
||||
if (bmOut)
|
||||
{
|
||||
delete t->m_cachedImage;
|
||||
t->m_cachedImage = bmOut;
|
||||
}
|
||||
else if (!t->m_cachedImage) t->m_cachedImage = new LICE_MemBitmap;
|
||||
|
||||
t->m_in_render=true;
|
||||
t->render(NULL,reqw,reqh);
|
||||
t->m_in_render=false;
|
||||
|
||||
LICE_IBitmap *ret = t->m_cachedImage;
|
||||
|
||||
t->m_cachedImage=NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LICE_DestroyLVG(void *lvg)
|
||||
{
|
||||
lvgImageCtx *t = (lvgImageCtx *)lvg;
|
||||
if (t && !t->m_par) delete t;
|
||||
}
|
||||
|
||||
class lvgRdContext : public ProjectStateContext
|
||||
{
|
||||
public:
|
||||
lvgRdContext(FILE *fp) { m_fp=fp; }
|
||||
virtual ~lvgRdContext() { }
|
||||
|
||||
virtual void AddLine(const char *fmt, ...) {};
|
||||
virtual int GetLine(char *buf, int buflen) // returns -1 on eof
|
||||
{
|
||||
if (!m_fp) return -1;
|
||||
for (;;)
|
||||
{
|
||||
buf[0]=0;
|
||||
fgets(buf,buflen,m_fp);
|
||||
if (!buf[0]) return -1;
|
||||
|
||||
char *p=buf;
|
||||
while (*p) p++;
|
||||
while (p>buf && (p[-1] == '\r' || p[-1]=='\n')) p--;
|
||||
*p=0;
|
||||
if (*buf) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
virtual WDL_INT64 GetOutputSize() { return 0; }
|
||||
virtual int GetTempFlag() { return 0; }
|
||||
virtual void SetTempFlag(int flag) {}
|
||||
|
||||
FILE *m_fp;
|
||||
};
|
||||
|
||||
void *LICE_LoadLVGFromContext(ProjectStateContext *ctx, const char *nameInfo, int defw, int defh)
|
||||
{
|
||||
if (!ctx) return NULL;
|
||||
|
||||
bool err=false;
|
||||
int ignoreBlockCnt=0;
|
||||
|
||||
lvgImageCtx *retimg = new lvgImageCtx(NULL);
|
||||
lvgImageCtx *curimg = NULL;
|
||||
|
||||
if (nameInfo)
|
||||
{
|
||||
curimg = retimg;
|
||||
curimg->m_base_w = defw;
|
||||
curimg->m_base_h = defh;
|
||||
}
|
||||
|
||||
while (!err)
|
||||
{
|
||||
char line[4096];
|
||||
line[0]=0;
|
||||
if (ctx->GetLine(line,sizeof(line))) break;
|
||||
|
||||
char *p=line;
|
||||
while (*p == ' ' || *p == '\t') p++;
|
||||
if (!*p) continue;
|
||||
|
||||
if (ignoreBlockCnt>0)
|
||||
{
|
||||
if (*p == '<') ignoreBlockCnt++;
|
||||
else if (*p == '>') ignoreBlockCnt--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*p == '<')
|
||||
{
|
||||
bool comment_state=false;
|
||||
LineParser lp(comment_state);
|
||||
if (!lp.parse(p)&&lp.getnumtokens()>=2 && !strcmp(lp.gettoken_str(0),"<LVG"))
|
||||
{
|
||||
if (!curimg)
|
||||
{
|
||||
// lp.gettoken_str(1) = version info string?
|
||||
curimg = retimg;
|
||||
}
|
||||
else
|
||||
{
|
||||
lvgImageCtx *img = new lvgImageCtx(curimg);
|
||||
curimg->m_images.Insert(lp.gettoken_str(1),img);
|
||||
curimg = img;
|
||||
}
|
||||
curimg->m_base_w = lp.gettoken_int(2);
|
||||
curimg->m_base_h = lp.gettoken_int(3);
|
||||
}
|
||||
else ignoreBlockCnt++;
|
||||
}
|
||||
else if (curimg)
|
||||
{
|
||||
if (*p == '>')
|
||||
{
|
||||
curimg = curimg->m_par;
|
||||
if (!curimg) break; // success!
|
||||
}
|
||||
else
|
||||
{
|
||||
curimg->m_lines.Add(strdup(p));
|
||||
}
|
||||
}
|
||||
|
||||
if (!curimg) err=true; // <LVG must be first non-whitespace line
|
||||
}
|
||||
}
|
||||
|
||||
if (err)
|
||||
{
|
||||
delete retimg;
|
||||
return 0;
|
||||
}
|
||||
return retimg;
|
||||
|
||||
}
|
||||
|
||||
void *LICE_LoadLVG(const char *filename)
|
||||
{
|
||||
FILE *fp=NULL;
|
||||
#if defined(_WIN32) && !defined(WDL_NO_SUPPORT_UTF8)
|
||||
#ifdef WDL_SUPPORT_WIN9X
|
||||
if (GetVersion()<0x80000000)
|
||||
#endif
|
||||
{
|
||||
WCHAR wf[2048];
|
||||
if (MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,filename,-1,wf,2048))
|
||||
fp = _wfopen(wf,L"rb");
|
||||
}
|
||||
#endif
|
||||
if (!fp) fp = WDL_fopenA(filename,"rb");
|
||||
|
||||
if (fp)
|
||||
{
|
||||
lvgRdContext ctx(fp);
|
||||
|
||||
void *p = LICE_LoadLVGFromContext(&ctx,NULL,0,0);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
469
oversampling/WDL/lice/lice_palette.cpp
Normal file
469
oversampling/WDL/lice/lice_palette.cpp
Normal file
@@ -0,0 +1,469 @@
|
||||
#include "lice.h"
|
||||
#include "../ptrlist.h"
|
||||
#include "../wdltypes.h"
|
||||
|
||||
|
||||
#define OCTREE_DEPTH 5 // every depth level adds 3 bits of RGB colorspace (depth 8 => 24-bit RGB)
|
||||
|
||||
struct ONode
|
||||
{
|
||||
WDL_INT64 colorcount; // number of color instances at or below this node
|
||||
WDL_INT64 sumrgb[3];
|
||||
int childflag; // 0=leaf, >0=index of single child, <0=branch
|
||||
int leafidx; // populated at the end
|
||||
ONode* next; // for OTree::branches
|
||||
ONode* children[8];
|
||||
};
|
||||
|
||||
struct OTree
|
||||
{
|
||||
int maxcolors;
|
||||
int leafcount;
|
||||
ONode* trunk;
|
||||
ONode* branches[OCTREE_DEPTH]; // linked lists of branches for each level of the tree
|
||||
ONode* spares;
|
||||
LICE_pixel* palette; // populated at the end
|
||||
bool palette_valid;
|
||||
};
|
||||
|
||||
|
||||
|
||||
int LICE_BuildPalette(LICE_IBitmap* bmp, LICE_pixel* palette, int maxcolors)
|
||||
{
|
||||
void* tree = LICE_CreateOctree(maxcolors);
|
||||
LICE_BuildOctree(tree, bmp);
|
||||
int sz = LICE_ExtractOctreePalette(tree, palette);
|
||||
LICE_DestroyOctree(tree);
|
||||
return sz;
|
||||
}
|
||||
|
||||
|
||||
static void AddColorToTree(OTree*, const LICE_pixel_chan *rgb);
|
||||
static int FindColorInTree(OTree*, const LICE_pixel_chan *rgb);
|
||||
static int PruneTree(OTree*);
|
||||
static void DeleteNode(OTree*, ONode*, ONode **delete_to);
|
||||
static int CollectLeaves(OTree*);
|
||||
static int CollectNodeLeaves(ONode* node, LICE_pixel* palette, int colorcount);
|
||||
|
||||
|
||||
void* LICE_CreateOctree(int maxcolors)
|
||||
{
|
||||
OTree* tree = new OTree;
|
||||
memset(tree, 0, sizeof(OTree));
|
||||
tree->maxcolors = maxcolors;
|
||||
tree->trunk = new ONode;
|
||||
memset(tree->trunk, 0, sizeof(ONode));
|
||||
tree->spares = NULL;
|
||||
return tree;
|
||||
}
|
||||
|
||||
|
||||
void LICE_ResetOctree(void *octree, int maxc)
|
||||
{
|
||||
OTree* tree = (OTree*)octree;
|
||||
if (!tree) return;
|
||||
|
||||
if (maxc > tree->maxcolors)
|
||||
{
|
||||
free(tree->palette);
|
||||
tree->palette=0;
|
||||
}
|
||||
|
||||
DeleteNode(tree, tree->trunk, &tree->spares);
|
||||
tree->leafcount = 0;
|
||||
tree->maxcolors = maxc;
|
||||
tree->palette_valid=false;
|
||||
memset(tree->branches,0,sizeof(tree->branches));
|
||||
|
||||
tree->trunk=tree->spares;
|
||||
if (tree->trunk) tree->spares = tree->trunk->next;
|
||||
else tree->trunk = new ONode;
|
||||
|
||||
memset(tree->trunk, 0, sizeof(ONode));
|
||||
}
|
||||
|
||||
void LICE_DestroyOctree(void* octree)
|
||||
{
|
||||
OTree* tree = (OTree*)octree;
|
||||
if (!tree) return;
|
||||
|
||||
DeleteNode(tree, tree->trunk, NULL);
|
||||
|
||||
ONode *p = tree->spares;
|
||||
while (p)
|
||||
{
|
||||
ONode *del = p;
|
||||
p = p->next;
|
||||
|
||||
delete del;
|
||||
}
|
||||
free(tree->palette);
|
||||
delete tree;
|
||||
}
|
||||
|
||||
|
||||
int LICE_BuildOctree(void* octree, LICE_IBitmap* bmp)
|
||||
{
|
||||
OTree* tree = (OTree*)octree;
|
||||
if (!tree || !bmp) return 0;
|
||||
|
||||
tree->palette_valid = false;
|
||||
|
||||
int y;
|
||||
const int h=bmp->getHeight();
|
||||
const int w=bmp->getWidth();
|
||||
const int rowspan = bmp->getRowSpan();
|
||||
const LICE_pixel *bits = bmp->getBits();
|
||||
for (y = 0; y < h; ++y)
|
||||
{
|
||||
const LICE_pixel *px = bits+y*rowspan;
|
||||
int x=w;
|
||||
while (x--)
|
||||
{
|
||||
AddColorToTree(tree, (const LICE_pixel_chan*)px);
|
||||
if (tree->leafcount > tree->maxcolors) PruneTree(tree);
|
||||
px++;
|
||||
}
|
||||
}
|
||||
|
||||
return tree->leafcount;
|
||||
}
|
||||
|
||||
int LICE_BuildOctreeForAlpha(void* octree, LICE_IBitmap* bmp, unsigned int minalpha)
|
||||
{
|
||||
OTree* tree = (OTree*)octree;
|
||||
if (!tree || !bmp) return 0;
|
||||
|
||||
tree->palette_valid = false;
|
||||
|
||||
int y;
|
||||
const int h=bmp->getHeight();
|
||||
const int w=bmp->getWidth();
|
||||
const int rowspan = bmp->getRowSpan();
|
||||
const LICE_pixel *bits = bmp->getBits();
|
||||
int pxcnt=0;
|
||||
for (y = 0; y < h; ++y)
|
||||
{
|
||||
const LICE_pixel *px = bits+y*rowspan;
|
||||
int x=w;
|
||||
while (x--)
|
||||
{
|
||||
if (px[LICE_PIXEL_A] >= minalpha)
|
||||
{
|
||||
AddColorToTree(tree, (const LICE_pixel_chan*)px);
|
||||
if (tree->leafcount > tree->maxcolors) PruneTree(tree);
|
||||
pxcnt++;
|
||||
}
|
||||
px++;
|
||||
}
|
||||
}
|
||||
|
||||
return pxcnt;
|
||||
}
|
||||
|
||||
|
||||
int LICE_BuildOctreeForDiff(void* octree, LICE_IBitmap* bmp, LICE_IBitmap* refbmp, LICE_pixel mask)
|
||||
{
|
||||
OTree* tree = (OTree*)octree;
|
||||
if (!tree || !bmp || !refbmp) return 0;
|
||||
|
||||
tree->palette_valid=false;
|
||||
|
||||
int y;
|
||||
const int h=lice_min(bmp->getHeight(),refbmp->getHeight());
|
||||
const int w=lice_min(bmp->getWidth(),refbmp->getWidth());
|
||||
|
||||
int rowspan = bmp->getRowSpan();
|
||||
int rowspan2 = refbmp->getRowSpan();
|
||||
const LICE_pixel *bits = bmp->getBits();
|
||||
const LICE_pixel *bits2 = refbmp->getBits();
|
||||
|
||||
if (bmp->isFlipped())
|
||||
{
|
||||
bits += rowspan * (bmp->getHeight()-1);
|
||||
rowspan = -rowspan;
|
||||
}
|
||||
|
||||
if (refbmp->isFlipped())
|
||||
{
|
||||
bits2 += rowspan2 * (refbmp->getHeight()-1);
|
||||
rowspan2 = -rowspan2;
|
||||
}
|
||||
|
||||
int pxcnt=0;
|
||||
for (y = 0; y < h; ++y)
|
||||
{
|
||||
const LICE_pixel * px = bits+y*rowspan;
|
||||
const LICE_pixel * px2 = bits2+y*rowspan2;
|
||||
int x=w;
|
||||
while (x--)
|
||||
{
|
||||
if ((*px ^ *px2) & mask)
|
||||
{
|
||||
AddColorToTree(tree, (const LICE_pixel_chan *)px);
|
||||
if (tree->leafcount > tree->maxcolors) PruneTree(tree);
|
||||
pxcnt++;
|
||||
}
|
||||
px++;
|
||||
px2++;
|
||||
}
|
||||
}
|
||||
|
||||
return pxcnt;
|
||||
}
|
||||
|
||||
|
||||
int LICE_FindInOctree(void* octree, LICE_pixel color)
|
||||
{
|
||||
OTree* tree = (OTree*)octree;
|
||||
if (!tree) return 0;
|
||||
|
||||
if (!tree->palette_valid) CollectLeaves(tree);
|
||||
|
||||
return FindColorInTree(tree, (const LICE_pixel_chan *)&color);
|
||||
}
|
||||
|
||||
|
||||
int LICE_ExtractOctreePalette(void* octree, LICE_pixel* palette)
|
||||
{
|
||||
OTree* tree = (OTree*)octree;
|
||||
if (!tree || !palette) return 0;
|
||||
|
||||
if (!tree->palette_valid) CollectLeaves(tree);
|
||||
|
||||
if (tree->palette) memcpy(palette, tree->palette, tree->maxcolors*sizeof(LICE_pixel));
|
||||
|
||||
return tree->leafcount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LICE_TestPalette(LICE_IBitmap* bmp, LICE_pixel* palette, int numcolors)
|
||||
{
|
||||
int x, y;
|
||||
for (y = 0; y < bmp->getHeight(); ++y)
|
||||
{
|
||||
LICE_pixel* px = bmp->getBits()+y*bmp->getRowSpan();
|
||||
for (x = 0; x < bmp->getWidth(); ++x)
|
||||
{
|
||||
const LICE_pixel col = px[x];
|
||||
const int rgb[3] = { (int)LICE_GETR(col), (int)LICE_GETG(col), (int)LICE_GETB(col) };
|
||||
|
||||
int minerr = 0x7FFFFFFF;
|
||||
int bestcol=-1;
|
||||
int i;
|
||||
for (i = 0; i < numcolors; ++i)
|
||||
{
|
||||
const LICE_pixel palcol = palette[i];
|
||||
const int rerr[3] = { rgb[0]-(int)LICE_GETR(palcol), rgb[1]-(int)LICE_GETG(palcol), rgb[2]-(int)LICE_GETB(palcol) };
|
||||
const int err = rerr[0]*rerr[0]+rerr[1]*rerr[1]+rerr[2]*rerr[2];
|
||||
if (err < minerr)
|
||||
{
|
||||
bestcol=i;
|
||||
minerr=err;
|
||||
}
|
||||
}
|
||||
px[x] = palette[bestcol];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AddColorToTree(OTree* tree, const LICE_pixel_chan *rgb)
|
||||
{
|
||||
ONode* p = tree->trunk;
|
||||
p->colorcount++;
|
||||
|
||||
int i;
|
||||
const unsigned char r = rgb[LICE_PIXEL_R];
|
||||
const unsigned char g = rgb[LICE_PIXEL_G];
|
||||
const unsigned char b = rgb[LICE_PIXEL_B];
|
||||
for (i = OCTREE_DEPTH-1; i >= 0; --i)
|
||||
{
|
||||
const int j = i+8-OCTREE_DEPTH;
|
||||
const unsigned char idx = (((r>>(j-2))&4))|(((g>>(j-1))&2))|((b>>j)&1);
|
||||
|
||||
ONode* np = p->children[idx];
|
||||
bool isleaf = false;
|
||||
|
||||
if (np)
|
||||
{
|
||||
isleaf = !np->childflag;
|
||||
}
|
||||
else // add node
|
||||
{
|
||||
if (!p->childflag) // first time down this path
|
||||
{
|
||||
p->childflag=idx+1;
|
||||
}
|
||||
else if (p->childflag > 0) // creating a new branch
|
||||
{
|
||||
p->childflag = -1;
|
||||
p->next = tree->branches[i];
|
||||
tree->branches[i] = p;
|
||||
}
|
||||
// else multiple branch, which we don't care about
|
||||
|
||||
np=tree->spares;
|
||||
if (np) tree->spares = np->next;
|
||||
else np = new ONode;
|
||||
|
||||
p->children[idx] = np;
|
||||
memset(np, 0, sizeof(ONode));
|
||||
}
|
||||
|
||||
np->sumrgb[0] += r;
|
||||
np->sumrgb[1] += g;
|
||||
np->sumrgb[2] += b;
|
||||
np->colorcount++;
|
||||
|
||||
if (isleaf) return;
|
||||
|
||||
p=np; // continue downward
|
||||
}
|
||||
|
||||
// p is a new leaf at the bottom
|
||||
tree->leafcount++;
|
||||
}
|
||||
|
||||
int FindColorInTree(OTree* tree, const LICE_pixel_chan *rgb)
|
||||
{
|
||||
ONode* p = tree->trunk;
|
||||
|
||||
int i;
|
||||
const unsigned char r=rgb[LICE_PIXEL_R];
|
||||
const unsigned char g=rgb[LICE_PIXEL_G];
|
||||
const unsigned char b=rgb[LICE_PIXEL_B];
|
||||
for (i = OCTREE_DEPTH-1; i >= 0; --i)
|
||||
{
|
||||
if (!p->childflag) break;
|
||||
|
||||
const int j = i+8-OCTREE_DEPTH;
|
||||
const unsigned char idx = (((r>>(j-2))&4))|(((g>>(j-1))&2))|((b>>j)&1);
|
||||
|
||||
ONode* np = p->children[idx];
|
||||
if (!np) break;
|
||||
|
||||
p = np;
|
||||
}
|
||||
|
||||
return p->leafidx;
|
||||
}
|
||||
|
||||
|
||||
int PruneTree(OTree* tree)
|
||||
{
|
||||
ONode* branch=0;
|
||||
int i;
|
||||
for (i = 0; i < OCTREE_DEPTH; ++i) // prune at the furthest level from the trunk
|
||||
{
|
||||
branch = tree->branches[i];
|
||||
if (branch)
|
||||
{
|
||||
tree->branches[i] = branch->next;
|
||||
branch->next=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (branch)
|
||||
{
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
if (branch->children[i])
|
||||
{
|
||||
DeleteNode(tree, branch->children[i],&tree->spares);
|
||||
branch->children[i]=0;
|
||||
}
|
||||
}
|
||||
branch->childflag=0; // now it's a leaf
|
||||
tree->leafcount++;
|
||||
}
|
||||
|
||||
return tree->leafcount;
|
||||
}
|
||||
|
||||
int CollectLeaves(OTree* tree)
|
||||
{
|
||||
if (!tree->palette) tree->palette = (LICE_pixel*)malloc(tree->maxcolors*sizeof(LICE_pixel));
|
||||
|
||||
if (!tree->palette) return 0;
|
||||
|
||||
int sz = CollectNodeLeaves(tree->trunk, tree->palette, 0);
|
||||
memset(tree->palette+sz, 0, (tree->maxcolors-sz)*sizeof(LICE_pixel));
|
||||
tree->palette_valid = true;
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
int CollectNodeLeaves(ONode* p, LICE_pixel* palette, int colorcount)
|
||||
{
|
||||
if (!p->childflag)
|
||||
{
|
||||
p->leafidx = colorcount;
|
||||
int r = (int)((double)p->sumrgb[0]/(double)p->colorcount);
|
||||
int g = (int)((double)p->sumrgb[1]/(double)p->colorcount);
|
||||
int b = (int)((double)p->sumrgb[2]/(double)p->colorcount);
|
||||
palette[colorcount++] = LICE_RGBA(r, g, b, 255);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p->childflag > 0)
|
||||
{
|
||||
colorcount = CollectNodeLeaves(p->children[p->childflag-1], palette, colorcount);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
if (p->children[i])
|
||||
{
|
||||
colorcount = CollectNodeLeaves(p->children[i], palette, colorcount);
|
||||
}
|
||||
}
|
||||
}
|
||||
// this is a branch or passthrough node, record the index
|
||||
// of any downtree leaf here so that we can return it for
|
||||
// color lookups that want to diverge off this node
|
||||
p->leafidx = colorcount-1;
|
||||
}
|
||||
|
||||
// colorcount should == leafcount
|
||||
return colorcount;
|
||||
}
|
||||
|
||||
|
||||
void DeleteNode(OTree* tree, ONode* p, ONode **delete_to)
|
||||
{
|
||||
if (!p->childflag)
|
||||
{
|
||||
tree->leafcount--;
|
||||
}
|
||||
else if (p->childflag > 0)
|
||||
{
|
||||
DeleteNode(tree, p->children[p->childflag-1],delete_to);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
if (p->children[i])
|
||||
{
|
||||
DeleteNode(tree, p->children[i],delete_to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (delete_to)
|
||||
{
|
||||
p->next = *delete_to;
|
||||
*delete_to = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
}
|
||||
|
||||
118
oversampling/WDL/lice/lice_pcx.cpp
Normal file
118
oversampling/WDL/lice/lice_pcx.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
Cockos WDL - LICE - Lightweight Image Compositing Engine
|
||||
Copyright (C) 2007 and later, Cockos Incorporated
|
||||
File: lice_pcx.cpp (PCX loading for LICE)
|
||||
See lice.h for license and other information
|
||||
*/
|
||||
|
||||
#include "lice.h"
|
||||
#include "../wdltypes.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// note: you'd never really want to use PCX files, but in case you do...
|
||||
|
||||
LICE_IBitmap *LICE_LoadPCX(const char *filename, LICE_IBitmap *_bmp)
|
||||
{
|
||||
FILE *fp = WDL_fopenA(filename,"rb");
|
||||
if(!fp) return 0;
|
||||
|
||||
fgetc(fp);
|
||||
if (fgetc(fp) != 5) { fclose(fp); return NULL; }
|
||||
if (fgetc(fp) != 1) { fclose(fp); return NULL; }
|
||||
if (fgetc(fp) != 8) { fclose(fp); return NULL; }
|
||||
|
||||
int sx = fgetc(fp); sx += fgetc(fp)<<8;
|
||||
int sy = fgetc(fp); sy += fgetc(fp)<<8;
|
||||
int ex = fgetc(fp); ex += fgetc(fp)<<8;
|
||||
int ey = fgetc(fp); ey += fgetc(fp)<<8;
|
||||
|
||||
|
||||
unsigned char pal[768];
|
||||
fseek(fp,-769,SEEK_END);
|
||||
if (fgetc(fp) != 12) { fclose(fp); return NULL; }
|
||||
if (fread(pal,1,768,fp) != 768 || feof(fp))
|
||||
{
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
LICE_IBitmap *usebmp = NULL;
|
||||
if (_bmp) (usebmp=_bmp)->resize(ex-sx+1,ey-sy+1);
|
||||
else usebmp = new WDL_NEW LICE_MemBitmap(ex-sx+1,ey-sy+1);
|
||||
if (!usebmp || usebmp->getWidth() != (ex-sx+1) || usebmp->getHeight() != (ey-sy+1))
|
||||
{
|
||||
if (usebmp != _bmp) delete usebmp;
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fseek(fp,128,SEEK_SET);
|
||||
|
||||
LICE_Clear(usebmp,0);
|
||||
int y = usebmp->getHeight();
|
||||
int w = usebmp->getWidth();
|
||||
int rowspan = usebmp->getRowSpan();
|
||||
LICE_pixel *pout = usebmp->getBits();
|
||||
if (usebmp->isFlipped())
|
||||
{
|
||||
pout += rowspan*(y-1);
|
||||
rowspan=-rowspan;
|
||||
}
|
||||
while (y--)
|
||||
{
|
||||
int xpos = 0;
|
||||
while (xpos < w)
|
||||
{
|
||||
int c = fgetc(fp);
|
||||
if (c&~255) break;
|
||||
if ((c & 192) == 192)
|
||||
{
|
||||
int oc = (fgetc(fp))&255;
|
||||
LICE_pixel t=LICE_RGBA(pal[oc*3],pal[oc*3+1],pal[oc*3+2],255);
|
||||
|
||||
c&=63;
|
||||
while (c-- && xpos<w) pout[xpos++] = t;
|
||||
}
|
||||
else pout[xpos++] = LICE_RGBA(pal[c*3],pal[c*3+1],pal[c*3+2],255);
|
||||
}
|
||||
pout+=rowspan;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
return usebmp;
|
||||
}
|
||||
|
||||
|
||||
class LICE_PCXLoader
|
||||
{
|
||||
public:
|
||||
_LICE_ImageLoader_rec rec;
|
||||
LICE_PCXLoader()
|
||||
{
|
||||
rec.loadfunc = loadfunc;
|
||||
rec.get_extlist = get_extlist;
|
||||
rec._next = LICE_ImageLoader_list;
|
||||
LICE_ImageLoader_list = &rec;
|
||||
}
|
||||
|
||||
static LICE_IBitmap *loadfunc(const char *filename, bool checkFileName, LICE_IBitmap *bmpbase)
|
||||
{
|
||||
if (checkFileName)
|
||||
{
|
||||
const char *p=filename;
|
||||
while (*p)p++;
|
||||
while (p>filename && *p != '\\' && *p != '/' && *p != '.') p--;
|
||||
if (stricmp(p,".pcx")) return 0;
|
||||
}
|
||||
return LICE_LoadPCX(filename,bmpbase);
|
||||
}
|
||||
static const char *get_extlist()
|
||||
{
|
||||
return "PCX files (*.PCX)\0*.PCX\0";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
LICE_PCXLoader LICE_pcxldr;
|
||||
375
oversampling/WDL/lice/lice_png.cpp
Normal file
375
oversampling/WDL/lice/lice_png.cpp
Normal file
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
Cockos WDL - LICE - Lightweight Image Compositing Engine
|
||||
Copyright (C) 2007 and later, Cockos Incorporated
|
||||
File: lice_png.cpp (PNG loading for LICE)
|
||||
See lice.h for license and other information
|
||||
*/
|
||||
|
||||
#include "lice.h"
|
||||
|
||||
#include "../wdltypes.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../libpng/png.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <CoreFoundation/CoreFoundation.h> // for loading images from embedded resource
|
||||
#endif
|
||||
|
||||
|
||||
LICE_IBitmap *LICE_LoadPNG(const char *filename, LICE_IBitmap *bmp)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
#if defined(_WIN32) && !defined(WDL_NO_SUPPORT_UTF8)
|
||||
#ifdef WDL_SUPPORT_WIN9X
|
||||
if (GetVersion()<0x80000000)
|
||||
#endif
|
||||
{
|
||||
WCHAR wf[2048];
|
||||
if (MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,filename,-1,wf,2048))
|
||||
fp = _wfopen(wf,L"rb");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!fp) fp = WDL_fopenA(filename,"rb");
|
||||
if (!fp) return 0;
|
||||
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if(!png_ptr)
|
||||
{
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if(!info_ptr)
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
unsigned int width, height;
|
||||
int bit_depth, color_type, interlace_type, compression_type, filter_method;
|
||||
png_get_IHDR(png_ptr, info_ptr, &width, &height,
|
||||
&bit_depth, &color_type, &interlace_type,
|
||||
&compression_type, &filter_method);
|
||||
|
||||
//convert whatever it is to RGBA
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_palette_to_rgb(png_ptr);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||
png_set_expand_gray_1_2_4_to_8(png_ptr);
|
||||
|
||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||
{
|
||||
png_set_tRNS_to_alpha(png_ptr);
|
||||
color_type |= PNG_COLOR_MASK_ALPHA;
|
||||
}
|
||||
|
||||
if (bit_depth == 16)
|
||||
png_set_strip_16(png_ptr);
|
||||
|
||||
if (bit_depth < 8)
|
||||
png_set_packing(png_ptr);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
|
||||
if (color_type & PNG_COLOR_MASK_ALPHA)
|
||||
png_set_swap_alpha(png_ptr);
|
||||
else
|
||||
png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
|
||||
|
||||
LICE_IBitmap *delbmp = NULL;
|
||||
|
||||
if (bmp) bmp->resize(width,height);
|
||||
else delbmp = bmp = new WDL_NEW LICE_MemBitmap(width,height);
|
||||
|
||||
if (!bmp || bmp->getWidth() != (int)width || bmp->getHeight() != (int)height)
|
||||
{
|
||||
delete delbmp;
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char **row_pointers=(unsigned char **)malloc(height*sizeof(unsigned char *));;
|
||||
LICE_pixel *srcptr = bmp->getBits();
|
||||
int dsrcptr=bmp->getRowSpan();
|
||||
if (bmp->isFlipped())
|
||||
{
|
||||
srcptr += dsrcptr*(bmp->getHeight()-1);
|
||||
dsrcptr=-dsrcptr;
|
||||
}
|
||||
unsigned int i;
|
||||
for(i=0;i<height;i++)
|
||||
{
|
||||
row_pointers[i]=(unsigned char *)srcptr;
|
||||
srcptr+=dsrcptr;
|
||||
}
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
fclose(fp);
|
||||
|
||||
#if !(LICE_PIXEL_A == 0 && LICE_PIXEL_R == 1 && LICE_PIXEL_G == 2 && LICE_PIXEL_B == 3)
|
||||
for(i=0;i<height;i++)
|
||||
{
|
||||
unsigned char *bp = row_pointers[i];
|
||||
int j=width;
|
||||
while (j-->0)
|
||||
{
|
||||
unsigned char a = bp[0];
|
||||
unsigned char r = bp[1];
|
||||
unsigned char g = bp[2];
|
||||
unsigned char b = bp[3];
|
||||
((LICE_pixel*)bp)[0] = LICE_RGBA(r,g,b,a);
|
||||
bp+=4;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
free(row_pointers);
|
||||
|
||||
return bmp;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char *data;
|
||||
int len;
|
||||
} pngReadStruct;
|
||||
|
||||
static void staticPngReadFunc(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
pngReadStruct *readStruct = (pngReadStruct *)png_get_io_ptr(png_ptr);
|
||||
memset(data, 0, length);
|
||||
|
||||
int l = (int)length;
|
||||
if (l > readStruct->len) l = readStruct->len;
|
||||
memcpy(data, readStruct->data, l);
|
||||
readStruct->data += l;
|
||||
readStruct->len -= l;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
LICE_IBitmap *LICE_LoadPNGFromNamedResource(const char *name, LICE_IBitmap *bmp) // returns a bitmap (bmp if nonzero) on success
|
||||
{
|
||||
char buf[2048];
|
||||
buf[0]=0;
|
||||
if (strlen(name)>400) return NULL; // max name for this is 400 chars
|
||||
|
||||
#ifdef __APPLE__
|
||||
CFBundleRef bund = CFBundleGetMainBundle();
|
||||
if (bund)
|
||||
{
|
||||
CFURLRef url=CFBundleCopyBundleURL(bund);
|
||||
if (url)
|
||||
{
|
||||
CFURLGetFileSystemRepresentation(url,true,(UInt8*)buf,sizeof(buf)-512);
|
||||
CFRelease(url);
|
||||
}
|
||||
}
|
||||
if (!buf[0]) return 0;
|
||||
strcat(buf,"/Contents/Resources/");
|
||||
#else
|
||||
int sz = readlink("/proc/self/exe", buf, sizeof(buf)-512);
|
||||
if (sz < 1)
|
||||
{
|
||||
static char tmp;
|
||||
// this will likely not work if the program was launched with a relative path
|
||||
// and the cwd has changed, but give it a try anyway
|
||||
Dl_info inf={0,};
|
||||
if (dladdr(&tmp,&inf) && inf.dli_fname)
|
||||
sz = (int) strlen(inf.dli_fname);
|
||||
else
|
||||
sz = 0;
|
||||
}
|
||||
|
||||
if ((unsigned int)sz >= sizeof(buf)-512) sz = sizeof(buf)-512-1;
|
||||
buf[sz]=0;
|
||||
char *p = buf;
|
||||
while (*p) p++;
|
||||
while (p > buf && *p != '/') p--;
|
||||
*p=0;
|
||||
strcat(buf,"/Resources/");
|
||||
#endif // !__APPLE__
|
||||
|
||||
strcat(buf,name);
|
||||
return LICE_LoadPNG(buf,bmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
LICE_IBitmap *LICE_LoadPNGFromMemory(const void *data_in, int buflen, LICE_IBitmap *bmp)
|
||||
{
|
||||
if (buflen<8) return NULL;
|
||||
unsigned char *data = (unsigned char *)(void*)data_in;
|
||||
if(png_sig_cmp(data, 0, 8)) return NULL;
|
||||
|
||||
pngReadStruct readStruct = {data, buflen};
|
||||
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if(!png_ptr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if(!info_ptr)
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_set_read_fn(png_ptr, &readStruct, staticPngReadFunc);
|
||||
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
unsigned int width, height;
|
||||
int bit_depth, color_type, interlace_type, compression_type, filter_method;
|
||||
png_get_IHDR(png_ptr, info_ptr, &width, &height,
|
||||
&bit_depth, &color_type, &interlace_type,
|
||||
&compression_type, &filter_method);
|
||||
|
||||
//convert whatever it is to RGBA
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_palette_to_rgb(png_ptr);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||
png_set_expand_gray_1_2_4_to_8(png_ptr);
|
||||
|
||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||
{
|
||||
png_set_tRNS_to_alpha(png_ptr);
|
||||
color_type |= PNG_COLOR_MASK_ALPHA;
|
||||
}
|
||||
|
||||
if (bit_depth == 16)
|
||||
png_set_strip_16(png_ptr);
|
||||
|
||||
if (bit_depth < 8)
|
||||
png_set_packing(png_ptr);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
|
||||
if (color_type & PNG_COLOR_MASK_ALPHA)
|
||||
png_set_swap_alpha(png_ptr);
|
||||
else
|
||||
png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
|
||||
|
||||
LICE_IBitmap *delbmp = NULL;
|
||||
|
||||
if (bmp) bmp->resize(width,height);
|
||||
else delbmp = bmp = new WDL_NEW LICE_MemBitmap(width,height);
|
||||
if (!bmp || bmp->getWidth() != (int)width || bmp->getHeight() != (int)height)
|
||||
{
|
||||
delete delbmp;
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char **row_pointers=(unsigned char **)malloc(height*sizeof(unsigned char *));;
|
||||
LICE_pixel *srcptr = bmp->getBits();
|
||||
int dsrcptr=bmp->getRowSpan();
|
||||
unsigned int i;
|
||||
for(i=0;i<height;i++)
|
||||
{
|
||||
row_pointers[i]=(unsigned char *)srcptr;
|
||||
srcptr+=dsrcptr;
|
||||
}
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
|
||||
//put shit in correct order
|
||||
#if !(LICE_PIXEL_A == 0 && LICE_PIXEL_R == 1 && LICE_PIXEL_G == 2 && LICE_PIXEL_B == 3)
|
||||
for(i=0;i<height;i++)
|
||||
{
|
||||
unsigned char *bp = row_pointers[i];
|
||||
int j=width;
|
||||
while (j-->0)
|
||||
{
|
||||
unsigned char a = bp[0];
|
||||
unsigned char r = bp[1];
|
||||
unsigned char g = bp[2];
|
||||
unsigned char b = bp[3];
|
||||
((LICE_pixel*)bp)[0] = LICE_RGBA(r,g,b,a);
|
||||
bp+=4;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
free(row_pointers);
|
||||
return bmp;
|
||||
}
|
||||
LICE_IBitmap *LICE_LoadPNGFromResource(HINSTANCE hInst, const char *resid, LICE_IBitmap *bmp)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HRSRC hResource = FindResource(hInst, resid, "PNG");
|
||||
if(!hResource) return NULL;
|
||||
|
||||
DWORD imageSize = SizeofResource(hInst, hResource);
|
||||
if(imageSize < 8) return NULL;
|
||||
|
||||
HGLOBAL res = LoadResource(hInst, hResource);
|
||||
const void* pResourceData = LockResource(res);
|
||||
if(!pResourceData) return NULL;
|
||||
|
||||
LICE_IBitmap * ret = LICE_LoadPNGFromMemory(pResourceData,imageSize,bmp);
|
||||
|
||||
// todo : cleanup res??
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
class LICE_PNGLoader
|
||||
{
|
||||
public:
|
||||
_LICE_ImageLoader_rec rec;
|
||||
LICE_PNGLoader()
|
||||
{
|
||||
rec.loadfunc = loadfunc;
|
||||
rec.get_extlist = get_extlist;
|
||||
rec._next = LICE_ImageLoader_list;
|
||||
LICE_ImageLoader_list = &rec;
|
||||
}
|
||||
|
||||
static LICE_IBitmap *loadfunc(const char *filename, bool checkFileName, LICE_IBitmap *bmpbase)
|
||||
{
|
||||
if (checkFileName)
|
||||
{
|
||||
const char *p=filename;
|
||||
while (*p)p++;
|
||||
while (p>filename && *p != '\\' && *p != '/' && *p != '.') p--;
|
||||
if (stricmp(p,".png")) return 0;
|
||||
}
|
||||
return LICE_LoadPNG(filename,bmpbase);
|
||||
}
|
||||
static const char *get_extlist()
|
||||
{
|
||||
return "PNG files (*.PNG)\0*.PNG\0";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
LICE_PNGLoader LICE_pngldr;
|
||||
133
oversampling/WDL/lice/lice_png_write.cpp
Normal file
133
oversampling/WDL/lice/lice_png_write.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
Cockos WDL - LICE - Lightweight Image Compositing Engine
|
||||
Copyright (C) 2007 and later, Cockos Incorporated
|
||||
File: lice_png_write.cpp (PNG saving for LICE)
|
||||
See lice.h for license and other information
|
||||
*/
|
||||
|
||||
#include "lice.h"
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../libpng/png.h"
|
||||
|
||||
|
||||
bool LICE_WritePNG(const char *filename, LICE_IBitmap *bmp, bool wantalpha /*=true*/)
|
||||
{
|
||||
if (!bmp || !filename) return false;
|
||||
/*
|
||||
** Joshua Teitelbaum 1/1/2008
|
||||
** Gifted to cockos for toe nail clippings.
|
||||
**
|
||||
** JF> tweaked some
|
||||
*/
|
||||
png_structp png_ptr=NULL;
|
||||
png_infop info_ptr=NULL;
|
||||
unsigned char *rowbuf=NULL;
|
||||
|
||||
FILE *fp=NULL;
|
||||
#if defined(_WIN32) && !defined(WDL_NO_SUPPORT_UTF8)
|
||||
#ifdef WDL_SUPPORT_WIN9X
|
||||
if (GetVersion()<0x80000000)
|
||||
#endif
|
||||
{
|
||||
WCHAR wf[2048];
|
||||
if (MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,filename,-1,wf,2048))
|
||||
fp = _wfopen(wf,L"wb");
|
||||
}
|
||||
#endif
|
||||
if (!fp) fp = fopen(filename,"wb");
|
||||
|
||||
if (fp == NULL) return false;
|
||||
|
||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL, NULL, NULL);
|
||||
|
||||
if (png_ptr == NULL) {
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == NULL) {
|
||||
fclose(fp);
|
||||
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
/* If we get here, we had a problem reading the file */
|
||||
if (fp) fclose(fp);
|
||||
fp=0;
|
||||
free(rowbuf);
|
||||
rowbuf=0;
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
int width=bmp->getWidth();
|
||||
int height = bmp->getHeight();
|
||||
|
||||
#define BITDEPTH 8
|
||||
png_set_IHDR(png_ptr, info_ptr, width, height, BITDEPTH, wantalpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
|
||||
png_set_bgr(png_ptr);
|
||||
|
||||
// kill alpha channel bytes if not wanted
|
||||
if (!wantalpha) png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
|
||||
|
||||
LICE_pixel *ptr=(LICE_pixel *)bmp->getBits();
|
||||
int rowspan=bmp->getRowSpan();
|
||||
if (bmp->isFlipped())
|
||||
{
|
||||
ptr+=rowspan*(bmp->getHeight()-1);
|
||||
rowspan=-rowspan;
|
||||
}
|
||||
|
||||
|
||||
if (LICE_PIXEL_B != 0 || LICE_PIXEL_G != 1 || LICE_PIXEL_R != 2 || LICE_PIXEL_A != 3)
|
||||
{
|
||||
rowbuf=(unsigned char *)malloc(width*4);
|
||||
int k;
|
||||
for (k = 0; k < height; k++)
|
||||
{
|
||||
int x;
|
||||
unsigned char *bout = rowbuf;
|
||||
LICE_pixel_chan *bin = (LICE_pixel_chan *) ptr;
|
||||
for(x=0;x<width;x++)
|
||||
{
|
||||
bout[0] = bin[LICE_PIXEL_B];
|
||||
bout[1] = bin[LICE_PIXEL_G];
|
||||
bout[2] = bin[LICE_PIXEL_R];
|
||||
bout[3] = bin[LICE_PIXEL_A];
|
||||
bout+=4;
|
||||
bin+=4;
|
||||
}
|
||||
png_write_row(png_ptr, (unsigned char *)rowbuf);
|
||||
ptr += rowspan;
|
||||
}
|
||||
free(rowbuf);
|
||||
rowbuf=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int k;
|
||||
for (k = 0; k < height; k++)
|
||||
{
|
||||
png_write_row(png_ptr, (unsigned char *)ptr);
|
||||
ptr += rowspan;
|
||||
}
|
||||
}
|
||||
|
||||
png_write_end(png_ptr, info_ptr);
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
|
||||
if (fp) fclose(fp);
|
||||
fp=0;
|
||||
|
||||
return true;
|
||||
}
|
||||
351
oversampling/WDL/lice/lice_texgen.cpp
Normal file
351
oversampling/WDL/lice/lice_texgen.cpp
Normal file
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
Cockos WDL - LICE - Lightweight Image Compositing Engine
|
||||
Copyright (C) 2007 and later, Cockos Incorporated
|
||||
File: lice_texgen.cpp (LICE texture generator routines)
|
||||
See lice.h for license and other information
|
||||
*/
|
||||
|
||||
|
||||
#ifndef WDL_NO_DEFINE_MINMAX
|
||||
#define WDL_NO_DEFINE_MINMAX
|
||||
#endif
|
||||
#include "lice.h"
|
||||
#include <math.h>
|
||||
|
||||
void LICE_TexGen_Marble(LICE_IBitmap *dest, const RECT *rect, float rv, float gv, float bv, float intensity)
|
||||
{
|
||||
int span=dest->getRowSpan();
|
||||
int w = dest->getWidth();
|
||||
int h = dest->getHeight();
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
if(rect)
|
||||
{
|
||||
x = rect->left;
|
||||
y = rect->top;
|
||||
w = rect->right - rect->left;
|
||||
h = rect->bottom - rect->top;
|
||||
}
|
||||
|
||||
if (x<0) { w+=x; x=0; }
|
||||
if (y<0) { h+=y; y=0; }
|
||||
|
||||
const int destbm_w = dest->getWidth(), destbm_h = dest->getHeight();
|
||||
if (w<1 || h < 1 || x >= destbm_w || y >= destbm_h) return;
|
||||
|
||||
if (w>destbm_w-x) w=destbm_w-x;
|
||||
if (h>destbm_h-y) h=destbm_h-y;
|
||||
|
||||
|
||||
LICE_pixel *startp = dest->getBits();
|
||||
if (dest->isFlipped())
|
||||
{
|
||||
startp += x + (dest->getHeight()-1-y)*span;
|
||||
span=-span;
|
||||
}
|
||||
else startp += x + y*span;
|
||||
|
||||
//simple 16bit marble noise generator
|
||||
|
||||
#define ROL(x,y) ((x<<(y))|(((unsigned short)x)>>(16-(y))))
|
||||
#define ROR(x,y) ((((unsigned short)x)>>(y))|(x<<(16-(y))))
|
||||
|
||||
intensity/=1024.0f;
|
||||
int maxc = 0;
|
||||
{
|
||||
LICE_pixel *p = startp;
|
||||
short n1 = 0, n2 = 0;
|
||||
for(int i=0;i<h;i++)
|
||||
{
|
||||
for(int j=0;j<w;j++)
|
||||
{
|
||||
n1 += n2;
|
||||
n1 = ROL(n1, n2&0xf);
|
||||
n2 += 2;
|
||||
n2 = ROR(n2, 1);
|
||||
|
||||
int val = (int)(n1*intensity)+1;
|
||||
|
||||
LICE_pixel c = w;
|
||||
LICE_pixel c2 = w/2;
|
||||
if(i>0)
|
||||
{
|
||||
c = p[j-span];
|
||||
if(j==0)
|
||||
c2 = p[(w-1)-span];
|
||||
else
|
||||
c2 = p[(j-1)-span];
|
||||
}
|
||||
|
||||
int pix = (((c + c2)/2) + val);
|
||||
if(pix>maxc) maxc = pix;
|
||||
p[j] = pix;
|
||||
}
|
||||
p+=span;
|
||||
}
|
||||
}
|
||||
|
||||
//normalize values and apply gamma
|
||||
{
|
||||
LICE_pixel *p = startp;
|
||||
float sc=255.0f/maxc;
|
||||
|
||||
for(int i=0;i<h;i++)
|
||||
{
|
||||
for(int j=0;j<w;j++)
|
||||
{
|
||||
float col = (float)fabs(p[j]*sc);
|
||||
p[j] = LICE_RGBA((int)(col*rv),(int)(col*gv),(int)(col*bv),255);
|
||||
}
|
||||
p+=span;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//standard perlin noise implementation
|
||||
#if 1
|
||||
int m_noiseTab[512];
|
||||
void initNoise()
|
||||
{
|
||||
static int init = 0;
|
||||
if(!init)
|
||||
{
|
||||
const int permutation[] = { 151,160,137,91,90,15,
|
||||
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
|
||||
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
|
||||
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
|
||||
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
|
||||
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
|
||||
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
|
||||
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
|
||||
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
|
||||
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
|
||||
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
|
||||
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
|
||||
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
|
||||
};
|
||||
for (int i=0; i < 256 ; i++)
|
||||
m_noiseTab[256+i] = m_noiseTab[i] = permutation[i];
|
||||
init = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static __inline float fade(float t)
|
||||
{
|
||||
return t * t * t * (t * (t * 6 - 15) + 10);
|
||||
}
|
||||
static __inline float lerp(float t, float a, float b)
|
||||
{
|
||||
return a + t * (b - a);
|
||||
}
|
||||
static __inline float grad(int hash, float x, float y)
|
||||
{
|
||||
//convert lo 4 bits of hash code into 12 gradient directions
|
||||
int h = hash & 15;
|
||||
float u = h<8 ? x : y,
|
||||
v = h<4 ? y : h==12||h==14 ? x : 0;
|
||||
return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
|
||||
}
|
||||
static float noise(float x, float y)
|
||||
{
|
||||
//find unit cube that contains point
|
||||
int X = (int)floor(x) & 255, Y = (int)floor(y) & 255;
|
||||
|
||||
//find relative x,y,z of point in cube
|
||||
x -= (float)floor(x);
|
||||
y -= (float)floor(y);
|
||||
|
||||
//compute fade curves for each of x,y,z
|
||||
float u = fade(x), v = fade(y);
|
||||
|
||||
//hash coordinates of the 8 cube corners
|
||||
int A = m_noiseTab[X ]+Y, AA = m_noiseTab[A], AB = m_noiseTab[A+1],
|
||||
B = m_noiseTab[X+1]+Y, BA = m_noiseTab[B], BB = m_noiseTab[B+1];
|
||||
|
||||
//and add blended results from 8 corners of cube
|
||||
return lerp(v, lerp(u, grad(m_noiseTab[AA ], x , y ),
|
||||
grad(m_noiseTab[BA ], x-1, y )),
|
||||
lerp(u, grad(m_noiseTab[AB ], x , y-1 ),
|
||||
grad(m_noiseTab[BB ], x-1, y-1 )));
|
||||
}
|
||||
#else
|
||||
//faster implementation but way lower quality
|
||||
#define noiseWidth 128
|
||||
#define noiseHeight 128
|
||||
|
||||
float m_noiseTab[noiseWidth][noiseHeight];
|
||||
|
||||
void initNoise()
|
||||
{
|
||||
static int init = 0;
|
||||
if(init) return;
|
||||
|
||||
for (int x = 0; x < noiseWidth; x++)
|
||||
for (int y = 0; y < noiseHeight; y++)
|
||||
{
|
||||
m_noiseTab[x][y] = (float)(rand() % 32768) / 32768.0;
|
||||
}
|
||||
|
||||
init = 1;
|
||||
}
|
||||
|
||||
float noise(float x, float y)
|
||||
{
|
||||
//x*=noiseWidth;
|
||||
//y*=noiseHeight;
|
||||
|
||||
//get fractional part of x and y
|
||||
float fractX = x - (int)x;
|
||||
float fractY = y - (int)y;
|
||||
|
||||
//wrap around
|
||||
int x1 = ((int)x + noiseWidth) % noiseWidth;
|
||||
int y1 = ((int)y + noiseHeight) % noiseHeight;
|
||||
|
||||
//neighbor values
|
||||
int x2 = (x1 + noiseWidth - 1) % noiseWidth;
|
||||
int y2 = (y1 + noiseHeight - 1) % noiseHeight;
|
||||
|
||||
//smooth the noise with bilinear interpolation
|
||||
float value = 0.0;
|
||||
value += fractX * fractY * m_noiseTab[x1][y1];
|
||||
value += fractX * (1 - fractY) * m_noiseTab[x1][y2];
|
||||
value += (1 - fractX) * fractY * m_noiseTab[x2][y1];
|
||||
value += (1 - fractX) * (1 - fractY) * m_noiseTab[x2][y2];
|
||||
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
|
||||
void LICE_TexGen_Noise(LICE_IBitmap *dest, const RECT *rect, float rv, float gv, float bv, float intensity, int mode, int smooth)
|
||||
{
|
||||
initNoise();
|
||||
|
||||
int span=dest->getRowSpan();
|
||||
int w = dest->getWidth();
|
||||
int h = dest->getHeight();
|
||||
int dx = 0;
|
||||
int dy = 0;
|
||||
if(rect)
|
||||
{
|
||||
dx = rect->left;
|
||||
dy = rect->top;
|
||||
w = rect->right - rect->left;
|
||||
h = rect->bottom - rect->top;
|
||||
}
|
||||
|
||||
if (dx<0) { w+=dx; dx=0; }
|
||||
if (dy<0) { h+=dy; dy=0; }
|
||||
const int destbm_w = dest->getWidth(), destbm_h = dest->getHeight();
|
||||
if (w<1 || h < 1 || dx >= destbm_w || dy >= destbm_h) return;
|
||||
|
||||
if (w>destbm_w-dx) w=destbm_w-dx;
|
||||
if (h>destbm_h-dy) h=destbm_h-dy;
|
||||
|
||||
LICE_pixel *startp = dest->getBits();
|
||||
if (dest->isFlipped())
|
||||
{
|
||||
startp += dx + (dest->getHeight()-1-dy)*span;
|
||||
span=-span;
|
||||
}
|
||||
else startp += dx + dy*span;
|
||||
|
||||
{
|
||||
LICE_pixel *p = startp;
|
||||
for(int i=0;i<h;i++)
|
||||
{
|
||||
for(int j=0;j<w;j++)
|
||||
{
|
||||
float x = (float)j/w*16*intensity;
|
||||
float y = (float)i/h*16*intensity;
|
||||
|
||||
float val = 0;
|
||||
int size = smooth;
|
||||
while(size>=1)
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case NOISE_MODE_NORMAL: val += noise(x/size, y/size)*size; break;
|
||||
case NOISE_MODE_WOOD: val += (float)cos( x/size + noise(x/size,y/size) )*size/2; break;
|
||||
}
|
||||
size /= 2;
|
||||
}
|
||||
float col = (float)fabs(val/smooth)*255;
|
||||
if(col>255) col=255;
|
||||
|
||||
p[j] = LICE_RGBA((int)(col*rv),(int)(col*gv),(int)(col*bv),255);
|
||||
}
|
||||
p+=span;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static float turbulence(int x, int y, float size, float isize)
|
||||
{
|
||||
float value = 0.0;
|
||||
const float initialSize = isize;
|
||||
while(size >= 1)
|
||||
{
|
||||
value += noise(x * isize, y * isize) * size;
|
||||
size *= 0.5f;
|
||||
isize *= 2.0f;
|
||||
}
|
||||
return(128.0f * value * initialSize);
|
||||
}
|
||||
|
||||
void LICE_TexGen_CircNoise(LICE_IBitmap *dest, const RECT *rect, float rv, float gv, float bv, float nrings, float power, int size)
|
||||
{
|
||||
initNoise();
|
||||
|
||||
int span=dest->getRowSpan();
|
||||
int w = dest->getWidth();
|
||||
int h = dest->getHeight();
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
if(rect)
|
||||
{
|
||||
x = rect->left;
|
||||
y = rect->top;
|
||||
w = rect->right - rect->left;
|
||||
h = rect->bottom - rect->top;
|
||||
}
|
||||
|
||||
if (x<0) { w+=x; x=0; }
|
||||
if (y<0) { h+=y; y=0; }
|
||||
const int destbm_w = dest->getWidth(), destbm_h = dest->getHeight();
|
||||
if (w<1 || h < 1 || x >= destbm_w || y >= destbm_h) return;
|
||||
|
||||
if (w>destbm_w-x) w=destbm_w-x;
|
||||
if (h>destbm_h-y) h=destbm_h-y;
|
||||
|
||||
LICE_pixel *startp = dest->getBits();
|
||||
if (dest->isFlipped())
|
||||
{
|
||||
startp += x + (dest->getHeight()-1-y)*span;
|
||||
span=-span;
|
||||
}
|
||||
else startp += x + y*span;
|
||||
|
||||
float xyPeriod = nrings;
|
||||
float turbPower = power;
|
||||
const float iturbSize = 1.0f/(float)size;
|
||||
const float turbSize = (float)size;
|
||||
|
||||
{
|
||||
LICE_pixel *p = startp;
|
||||
for(int i=0;i<h;i++)
|
||||
{
|
||||
for(int j=0;j<w;j++)
|
||||
{
|
||||
float xValue = ((float)j - w / 2) / w;
|
||||
float yValue = ((float)i - h / 2) / h;
|
||||
|
||||
float distValue = (float) (sqrt(xValue * xValue + yValue * yValue) + turbPower * turbulence(j, i, turbSize, iturbSize) / 256.0);
|
||||
float col = (float)fabs(256.0 * sin(2 * xyPeriod * distValue * 3.14159));
|
||||
|
||||
p[j] = LICE_RGBA((int)(col*rv),(int)(col*bv),(int)(col*gv),255);
|
||||
}
|
||||
p+=span;
|
||||
}
|
||||
}
|
||||
}
|
||||
1392
oversampling/WDL/lice/lice_text.cpp
Normal file
1392
oversampling/WDL/lice/lice_text.cpp
Normal file
File diff suppressed because it is too large
Load Diff
274
oversampling/WDL/lice/lice_text.h
Normal file
274
oversampling/WDL/lice/lice_text.h
Normal file
@@ -0,0 +1,274 @@
|
||||
#ifndef _LICE_TEXT_H_
|
||||
#define _LICE_TEXT_H_
|
||||
|
||||
#include "lice.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include "../swell/swell.h"
|
||||
#endif
|
||||
#include "../heapbuf.h"
|
||||
|
||||
#define LICE_FONT_FLAG_VERTICAL 1 // rotate text to vertical (do not set the windows font to vertical though)
|
||||
#define LICE_FONT_FLAG_VERTICAL_BOTTOMUP 2
|
||||
|
||||
#define LICE_FONT_FLAG_PRECALCALL 4
|
||||
//#define LICE_FONT_FLAG_ALLOW_NATIVE 8
|
||||
#define LICE_FONT_FLAG_FORCE_NATIVE 1024
|
||||
|
||||
#define LICE_FONT_FLAG_FX_BLUR 16
|
||||
#define LICE_FONT_FLAG_FX_INVERT 32
|
||||
#define LICE_FONT_FLAG_FX_MONO 64 // faster but no AA/etc
|
||||
|
||||
#define LICE_FONT_FLAG_FX_SHADOW 128 // these imply MONO
|
||||
#define LICE_FONT_FLAG_FX_OUTLINE 256
|
||||
|
||||
#define LICE_FONT_FLAG_OWNS_HFONT 512
|
||||
|
||||
// could do a mask for these flags
|
||||
#define LICE_FONT_FLAGS_HAS_FX(flag) \
|
||||
(flag&(LICE_FONT_FLAG_VERTICAL|LICE_FONT_FLAG_VERTICAL_BOTTOMUP| \
|
||||
LICE_FONT_FLAG_FX_BLUR|LICE_FONT_FLAG_FX_INVERT|LICE_FONT_FLAG_FX_MONO| \
|
||||
LICE_FONT_FLAG_FX_SHADOW|LICE_FONT_FLAG_FX_OUTLINE))
|
||||
|
||||
#define LICE_DT_NEEDALPHA 0x80000000 // include in DrawText() if the output alpha channel is important
|
||||
#define LICE_DT_USEFGALPHA 0x40000000 // uses alpha channel in fg color
|
||||
|
||||
class LICE_IFont
|
||||
{
|
||||
public:
|
||||
virtual ~LICE_IFont() {}
|
||||
|
||||
virtual void SetFromHFont(HFONT font, int flags=0)=0; // hfont must REMAIN valid, unless LICE_FONT_FLAG_PRECALCALL or LICE_FONT_FLAG_OWNS_HFONT set (OWNS means LICE_IFont will clean up hfont on font change or exit)
|
||||
|
||||
virtual LICE_pixel SetTextColor(LICE_pixel color)=0;
|
||||
virtual LICE_pixel SetBkColor(LICE_pixel color)=0;
|
||||
virtual LICE_pixel SetEffectColor(LICE_pixel color)=0;
|
||||
virtual int SetBkMode(int bkmode)=0;
|
||||
virtual void SetCombineMode(int combine, float alpha=1.0f)=0;
|
||||
|
||||
virtual int DrawText(LICE_IBitmap *bm, const char *str, int strcnt, RECT *rect, UINT dtFlags)=0;
|
||||
|
||||
virtual LICE_pixel GetTextColor()=0;
|
||||
virtual HFONT GetHFont()=0;
|
||||
virtual int GetLineHeight()=0;
|
||||
virtual void SetLineSpacingAdjust(int amt)=0;
|
||||
};
|
||||
|
||||
|
||||
#ifndef LICE_TEXT_NO_DECLARE_CACHEDFONT
|
||||
|
||||
class LICE_CachedFont : public LICE_IFont
|
||||
{
|
||||
public:
|
||||
LICE_CachedFont();
|
||||
virtual ~LICE_CachedFont();
|
||||
|
||||
virtual void SetFromHFont(HFONT font, int flags=0);
|
||||
|
||||
virtual LICE_pixel SetTextColor(LICE_pixel color) { LICE_pixel ret=m_fg; m_fg=color; return ret; }
|
||||
virtual LICE_pixel SetBkColor(LICE_pixel color) { LICE_pixel ret=m_bg; m_bg=color; return ret; }
|
||||
virtual LICE_pixel SetEffectColor(LICE_pixel color) { LICE_pixel ret=m_effectcol; m_effectcol=color; return ret; }
|
||||
virtual int SetBkMode(int bkmode) { int bk = m_bgmode; m_bgmode=bkmode; return bk; }
|
||||
virtual void SetCombineMode(int combine, float alpha=1.0f) { m_comb=combine; m_alpha=alpha; }
|
||||
|
||||
virtual int DrawText(LICE_IBitmap *bm, const char *str, int strcnt, RECT *rect, UINT dtFlags)
|
||||
{
|
||||
return DrawTextImpl(bm,str,strcnt,rect,dtFlags);
|
||||
}
|
||||
|
||||
virtual LICE_pixel GetTextColor() { return m_fg; }
|
||||
virtual HFONT GetHFont() { return m_font; }
|
||||
virtual int GetLineHeight() { return m_line_height; }
|
||||
|
||||
virtual void SetLineSpacingAdjust(int amt) { m_lsadj=amt; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool DrawGlyph(LICE_IBitmap *bm, unsigned short c, int xpos, int ypos, const RECT *clipR);
|
||||
int DrawTextImpl(LICE_IBitmap *bm, const char *str, int strcnt, RECT *rect, UINT dtFlags); // cause swell defines DrawText to SWELL_DrawText etc
|
||||
|
||||
bool RenderGlyph(unsigned short idx);
|
||||
|
||||
const char *NextWordBreak(const char *str, int strcnt, int w);
|
||||
|
||||
LICE_pixel m_fg,m_bg,m_effectcol;
|
||||
int m_bgmode;
|
||||
int m_comb;
|
||||
float m_alpha;
|
||||
int m_flags;
|
||||
|
||||
int m_line_height,m_lsadj;
|
||||
struct charEnt
|
||||
{
|
||||
int base_offset; // offset in m_cachestore+1, so 1=offset0, 0=unset, -1=failed to render
|
||||
int width, height;
|
||||
int advance;
|
||||
int charid; // used by m_extracharlist
|
||||
int left_extra;
|
||||
};
|
||||
charEnt *findChar(unsigned short c);
|
||||
|
||||
charEnt m_lowchars[128]; // first 128 chars cached here
|
||||
WDL_TypedBuf<charEnt> m_extracharlist;
|
||||
WDL_TypedBuf<unsigned char> m_cachestore;
|
||||
|
||||
static int _charSortFunc(const void *a, const void *b);
|
||||
|
||||
HFONT m_font;
|
||||
|
||||
};
|
||||
|
||||
#endif // !LICE_TEXT_NO_DECLARE_CACHEDFONT
|
||||
|
||||
#ifndef LICE_TEXT_NO_MULTIDPI
|
||||
class __LICE_dpiAwareFont : public LICE_IFont
|
||||
{
|
||||
struct rec {
|
||||
LICE_IFont *cache;
|
||||
int sz;
|
||||
};
|
||||
WDL_TypedBuf<rec> m_list; // used entries are at end of list, most recently used last. sz=0 for unused
|
||||
|
||||
int (*m_getflags)(int);
|
||||
int m_flags;
|
||||
LICE_pixel m_fg, m_bg, m_effectcol;
|
||||
int m_bgmode, m_comb;
|
||||
float m_alpha;
|
||||
int m_lsadj;
|
||||
|
||||
public:
|
||||
LOGFONT m_lf;
|
||||
|
||||
|
||||
// LICE_IFont interface
|
||||
virtual void SetFromHFont(HFONT font, int flags=0) { }
|
||||
|
||||
virtual LICE_pixel SetTextColor(LICE_pixel color) { LICE_pixel ret=m_fg; m_fg=color; return ret; }
|
||||
virtual LICE_pixel SetBkColor(LICE_pixel color) { LICE_pixel ret=m_bg; m_bg=color; return ret; }
|
||||
virtual LICE_pixel SetEffectColor(LICE_pixel color) { LICE_pixel ret=m_effectcol; m_effectcol=color; return ret; }
|
||||
virtual int SetBkMode(int bkmode) { int bk = m_bgmode; m_bgmode=bkmode; return bk; }
|
||||
virtual void SetCombineMode(int combine, float alpha=1.0f) { m_comb=combine; m_alpha=alpha; }
|
||||
|
||||
virtual int DrawText(LICE_IBitmap *bm, const char *str, int strcnt, RECT *rect, UINT dtFlags)
|
||||
{
|
||||
LICE_IFont *f = get(bm);
|
||||
if (!f) return 0;
|
||||
if (!(dtFlags & DT_CALCRECT))
|
||||
{
|
||||
f->SetTextColor(m_fg);
|
||||
f->SetBkColor(m_bg);
|
||||
f->SetEffectColor(m_effectcol);
|
||||
f->SetBkMode(m_bgmode);
|
||||
f->SetCombineMode(m_comb,m_alpha);
|
||||
f->SetLineSpacingAdjust(m_lsadj);
|
||||
}
|
||||
return f->DrawText(bm,str,strcnt,rect,dtFlags);
|
||||
}
|
||||
|
||||
virtual LICE_pixel GetTextColor() { return m_fg; }
|
||||
virtual HFONT GetHFont() { return NULL; }
|
||||
virtual int GetLineHeight() { return GetLineHeightDPI(NULL); }
|
||||
|
||||
virtual void SetLineSpacingAdjust(int amt) { m_lsadj=amt; }
|
||||
|
||||
__LICE_dpiAwareFont(int maxsz)
|
||||
{
|
||||
memset(&m_lf,0,sizeof(m_lf));
|
||||
m_getflags = NULL;
|
||||
m_flags=0;
|
||||
m_fg=m_bg=m_effectcol=0;
|
||||
m_bgmode=TRANSPARENT;
|
||||
m_comb=0;
|
||||
m_alpha=1.0;
|
||||
m_lsadj=0;
|
||||
|
||||
rec *l = m_list.ResizeOK(maxsz);
|
||||
if (l) memset(l,0,sizeof(*l)*maxsz);
|
||||
}
|
||||
~__LICE_dpiAwareFont()
|
||||
{
|
||||
for (int x = 0; x < m_list.GetSize(); x ++) delete m_list.Get()[x].cache;
|
||||
}
|
||||
void SetFromLogFont(LOGFONT *lf, int (*get_flags)(int))
|
||||
{
|
||||
m_lf = *lf;
|
||||
m_getflags = get_flags;
|
||||
m_flags = get_flags ? get_flags(0) : 0;
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
int x = m_list.GetSize()-1;
|
||||
rec *t = m_list.Get();
|
||||
while (x>=0 && t[x].sz) t[x--].sz=0;
|
||||
}
|
||||
|
||||
LICE_IFont *get_for_sc(int fsc)
|
||||
{
|
||||
int use_flag = m_getflags ? m_getflags(0) & ~LICE_FONT_FLAG_PRECALCALL : 0;
|
||||
if (m_flags != use_flag)
|
||||
{
|
||||
m_flags = use_flag;
|
||||
clear();
|
||||
}
|
||||
|
||||
int ht = m_lf.lfHeight, ht2 = m_lf.lfWidth;
|
||||
if (fsc && fsc != 256)
|
||||
{
|
||||
ht = (ht * fsc) / 256;
|
||||
ht2 = (ht2 * fsc) / 256;
|
||||
use_flag |= LICE_FONT_FLAG_FORCE_NATIVE;
|
||||
}
|
||||
|
||||
int x = m_list.GetSize()-1;
|
||||
rec *t = m_list.Get();
|
||||
while (x>=0 && t[x].sz != ht && t[x].sz) x--;
|
||||
if (x<0) t[x=0].sz = 0; // if list full, use oldest item
|
||||
|
||||
// move to end of list
|
||||
if (x != m_list.GetSize()-1)
|
||||
{
|
||||
rec tmp = t[x];
|
||||
m_list.Delete(x);
|
||||
m_list.Add(tmp);
|
||||
}
|
||||
|
||||
t = m_list.Get() + m_list.GetSize() - 1;
|
||||
if (!t->cache) t->cache = __CreateFont();
|
||||
if (!t->sz && t->cache)
|
||||
{
|
||||
t->sz = ht;
|
||||
LOGFONT lf = m_lf;
|
||||
lf.lfHeight = ht;
|
||||
lf.lfWidth = ht2;
|
||||
#ifdef _WIN32
|
||||
if (!(m_flags & LICE_FONT_FLAG_FORCE_NATIVE) && abs(lf.lfHeight) <= 14) lf.lfQuality = NONANTIALIASED_QUALITY;
|
||||
#endif
|
||||
t->cache->SetFromHFont(CreateFontIndirect(&lf), LICE_FONT_FLAG_OWNS_HFONT | use_flag);
|
||||
}
|
||||
|
||||
return t->cache;
|
||||
}
|
||||
LICE_IFont *get(LICE_IBitmap *bm)
|
||||
{
|
||||
return get_for_sc(bm ? (int)bm->Extended(LICE_EXT_GET_ANY_SCALING,NULL) : 0);
|
||||
}
|
||||
|
||||
|
||||
int GetLineHeightDPI(LICE_IBitmap *bm)
|
||||
{
|
||||
LICE_IFont *f = get(bm);
|
||||
return f ? f->GetLineHeight() : 10;
|
||||
}
|
||||
virtual LICE_IFont *__CreateFont()=0;
|
||||
};
|
||||
|
||||
template<class BASEFONT> class LICE_dpiAwareFont : public __LICE_dpiAwareFont {
|
||||
public:
|
||||
LICE_dpiAwareFont(int max) : __LICE_dpiAwareFont(max) { }
|
||||
virtual LICE_IFont *__CreateFont() { return new BASEFONT; }
|
||||
};
|
||||
#endif//LICE_TEXT_NO_MULTIDPI
|
||||
|
||||
#endif//_LICE_TEXT_H_
|
||||
1356
oversampling/WDL/lice/lice_textnew.cpp
Normal file
1356
oversampling/WDL/lice/lice_textnew.cpp
Normal file
File diff suppressed because it is too large
Load Diff
5
oversampling/WDL/lice/test/.gitignore
vendored
Normal file
5
oversampling/WDL/lice/test/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
Win32/Debug/
|
||||
Win32/Release/
|
||||
x64/Debug/
|
||||
x64/Release/
|
||||
|
||||
68
oversampling/WDL/lice/test/Makefile
Normal file
68
oversampling/WDL/lice/test/Makefile
Normal file
@@ -0,0 +1,68 @@
|
||||
CFLAGS=-O2 -g -Wall
|
||||
LFLAGS=
|
||||
CC=gcc
|
||||
CXX=g++
|
||||
WDL_PATH=../..
|
||||
|
||||
CFLAGS += -D_FILE_OFFSET_BITS=64
|
||||
|
||||
ifdef NOSWELL
|
||||
CFLAGS += -D_LICE_NO_SYSBITMAPS_
|
||||
SWELL_OBJS =
|
||||
else
|
||||
CFLAGS += -DSWELL_LICE_GDI
|
||||
|
||||
ifdef GDK2
|
||||
CFLAGS += -DSWELL_TARGET_GDK=2 $(shell pkg-config --cflags gdk-2.0)
|
||||
LFLAGS += $(shell pkg-config --libs gdk-2.0) -lX11 -lXi
|
||||
else
|
||||
CFLAGS += -DSWELL_TARGET_GDK=3 $(shell pkg-config --cflags gdk-3.0)
|
||||
LFLAGS += $(shell pkg-config --libs gdk-3.0) -lX11 -lXi
|
||||
endif
|
||||
ifndef NOFREETYPE
|
||||
CFLAGS += -DSWELL_FREETYPE $(shell pkg-config --cflags freetype2)
|
||||
LFLAGS += $(shell pkg-config --libs freetype2)
|
||||
endif
|
||||
|
||||
SWELL_OBJS = swell-wnd-generic.o swell-gdi-lice.o swell.o swell-misc-generic.o \
|
||||
swell-dlg-generic.o swell-menu-generic.o swell-kb-generic.o \
|
||||
swell-gdi-generic.o swell-ini.o swell-generic-gdk.o \
|
||||
swell-appstub-generic.o swell-miscdlg-generic.o
|
||||
|
||||
LFLAGS += -ldl
|
||||
|
||||
vpath %.cpp $(WDL_PATH)/swell
|
||||
endif
|
||||
|
||||
CXXFLAGS=$(CFLAGS)
|
||||
|
||||
vpath %.c $(WDL_PATH)/zlib $(WDL_PATH)/libpng $(WDL_PATH)/jpeglib $(WDL_PATH)/giflib
|
||||
vpath %.cpp $(WDL_PATH)/lice $(WDL_PATH)/plush2
|
||||
|
||||
ZLIB_OBJS = compress.o adler32.o crc32.o deflate.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o ioapi.o zip.o unzip.o
|
||||
|
||||
PNGLIB_OBJS = png.o pngerror.o pngget.o pngmem.o pngpread.o pngread.o pngrio.o pngrtran.o pngrutil.o pngset.o pngtrans.o
|
||||
|
||||
JPEGLIB_OBJS = jcomapi.o jdapimin.o jdapistd.o jdatadst.o jdatasrc.o jdcoefct.o jdcolor.o jddctmgr.o jdhuff.o jdinput.o jdmainct.o jdmarker.o \
|
||||
jdmaster.o jdmerge.o jdphuff.o jdpostct.o jdsample.o jerror.o jfdctflt.o jfdctfst.o jfdctint.o jidctflt.o jidctfst.o jidctint.o \
|
||||
jidctred.o jmemmgr.o jmemnobs.o jquant1.o jquant2.o jutils.o
|
||||
|
||||
GIFLIB_OBJS = dgif_lib.o egif_lib.o gifalloc.o gif_hash.o
|
||||
|
||||
LICEOBJS = lice.o lice_gif.o lice_gif_write.o lice_image.o lice_jpg.o lice_png.o lice_pcx.o lice_palette.o lice_line.o lice_arc.o lice_text.o lice_textnew.o lice_texgen.o lice_colorspace.o
|
||||
|
||||
PLUSH_OBJS = pl_cam.o pl_make.o pl_math.o pl_obj.o pl_putface.o pl_read_3ds.o pl_read_cob.o pl_read_jaw.o pl_spline.o
|
||||
|
||||
.phony: clean default
|
||||
|
||||
default: test
|
||||
|
||||
test: $(LICEOBJS) $(JPEGLIB_OBJS) $(PNGLIB_OBJS) $(ZLIB_OBJS) $(GIFLIB_OBJS) $(SWELL_OBJS) $(PLUSH_OBJS) main.o fly.o
|
||||
$(CXX) $(CFLAGS) -o $@ $^ $(LFLAGS)
|
||||
|
||||
|
||||
imgs2gif: $(LICEOBJS) $(JPEGLIB_OBJS) $(PNGLIB_OBJS) $(ZLIB_OBJS) $(GIFLIB_OBJS) $(SWELL_OBJS) imgs2gif.o
|
||||
$(CXX) $(CFLAGS) -o $@ $^ $(LFLAGS)
|
||||
|
||||
clean:
|
||||
-rm $(LICEOBJS) $(JPEGLIB_OBJS) $(PNGLIB_OBJS) $(ZLIB_OBJS) $(GIFLIB_OBJS) imgs2gif.o imgs2gif $(SWELL_OBJS) $(PLUSH_OBJS) test main.o fly.o
|
||||
1137
oversampling/WDL/lice/test/main.cpp
Normal file
1137
oversampling/WDL/lice/test/main.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user