From 7bcfae18b76f8903400ddb46db4f1459fb644f2d Mon Sep 17 00:00:00 2001 From: Rodrigo Braz Monteiro Date: Sun, 3 Dec 2006 00:33:20 +0000 Subject: [PATCH] Merged Azzy's libass patch Originally committed to SVN as r558. --- configure.ac | 8 ++ core/Makefile.am | 2 + core/subtitle_provider_libass.cpp | 180 ++++++++++++++++++++++++++++++ core/video_provider_lavc.cpp | 2 +- 4 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 core/subtitle_provider_libass.cpp diff --git a/configure.ac b/configure.ac index e9e07ee90..120f157ba 100644 --- a/configure.ac +++ b/configure.ac @@ -98,6 +98,13 @@ PKG_CHECK_MODULES([ASA], asa >= 0.3.2, [ ], [true]) AC_CHECK_HEADERS([asa/asa.h]) +PKG_CHECK_MODULES([LIBASS], libass >= 0.9.1, [ + CPPFLAGS="$CPPFLAGS $LIBASS_CFLAGS" + LIBS="$LIBS $LIBASS_LIBS" + AC_DEFINE(HAVE_LIBASS, 1, [found libass via pkg-config]) +], [true]) +AC_CHECK_HEADERS([ass/ass.h]) + PKG_CHECK_MODULES([GLIB], glib-2.0, [ CPPFLAGS="$CPPFLAGS $GLIB_CFLAGS" LIBS="$LIBS $GLIB_LIBS" @@ -150,3 +157,4 @@ AC_OUTPUT([ core/bitmaps/Makefile ]) + diff --git a/core/Makefile.am b/core/Makefile.am index 5e9ecd7e2..bca5b3f98 100644 --- a/core/Makefile.am +++ b/core/Makefile.am @@ -85,6 +85,7 @@ aegisub_SOURCES = about.cpp \ subtitle_format_txt.cpp \ subtitle_provider.cpp \ subtitle_provider_asa.cpp \ + subtitle_provider_libass.cpp \ text_file_reader.cpp \ text_file_writer.cpp \ timeedit_ctrl.cpp \ @@ -104,3 +105,4 @@ aegisub_SOURCES = about.cpp \ yatta_wrap.cpp \ MatroskaParser.c + diff --git a/core/subtitle_provider_libass.cpp b/core/subtitle_provider_libass.cpp new file mode 100644 index 000000000..b8aa6a9fa --- /dev/null +++ b/core/subtitle_provider_libass.cpp @@ -0,0 +1,180 @@ +// -*- c-basic-offset: 8; indent-tabs-mode: t -*- +// Copyright (c) 2006, David Lamparter +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// ----------------------------------------------------------------------------- +// +// AEGISUB +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:zeratul@cellosoft.com +// + +/////////// +// Headers +#ifdef HAVE_LIBASS + +#include +#include +#include "subtitle_provider.h" +#include "video_provider.h" +#include "ass_file.h" + +extern "C" { +#include +} + +class SubtitleProviderLibASS : public SubtitleProvider, SubtitleProvider::Overlay { +private: + class MyClass : public Class { + public: + MyClass() : Class(L"libass") { + ass_library = ass_library_init(); + if (!ass_library) throw _T("ass_library_init failed"); + + ass_set_fonts_dir(ass_library, ""); + ass_set_extract_fonts(ass_library, 0); + ass_set_style_overrides(ass_library, NULL); + }; + virtual SubtitleProvider *Get(AssFile *subs) { return new SubtitleProviderLibASS(subs); }; + }; + static MyClass me; + + static ass_library_t* ass_library; + ass_renderer_t* ass_renderer; + ass_track_t* ass_track; + wxString last_sub; + + AssFile *subs; + VideoProvider *vpro; +public: + SubtitleProviderLibASS(AssFile *_subs); + virtual ~SubtitleProviderLibASS(); + virtual void Bind(VideoProvider *_vpro); + + virtual void SetParams(int width, int height); + virtual void Render(wxImage &frame, int ms); + virtual void Unbind(); +}; + +SubtitleProviderLibASS::MyClass SubtitleProviderLibASS::me; +ass_library_t* SubtitleProviderLibASS::ass_library; + +SubtitleProviderLibASS::SubtitleProviderLibASS(AssFile *_subs) : ass_track(NULL) +{ + subs = _subs; + wxString text = subs->GetString(); + + ass_renderer = ass_renderer_init(ass_library); + if (!ass_renderer) throw _T("ass_renderer_init failed"); + + //ass_set_margins(ass_renderer, 0, 0, 0, 0); + //ass_set_use_margins(ass_renderer, 0); + ass_set_font_scale(ass_renderer, 1.); + ass_set_fonts(ass_renderer, NULL, "Sans"); +}; + +SubtitleProviderLibASS::~SubtitleProviderLibASS() +{ + Unbind(); + //asa_close(inst); +}; + +void SubtitleProviderLibASS::Bind(VideoProvider *_vpro) +{ + vpro = _vpro; + vpro->AttachOverlay(this); +} + +void SubtitleProviderLibASS::SetParams(int width, int height) +{ + ass_set_frame_size(ass_renderer, width, height); +} + +#define _r(c) ((c)>>24) +#define _g(c) (((c)>>16)&0xFF) +#define _b(c) (((c)>>8)&0xFF) +#define _a(c) ((c)&0xFF) + +static void blend_single(wxImage &frame, ass_image_t* img) { + unsigned char opacity = 255 - _a(img->color); + unsigned char r = _r(img->color); + unsigned char g = _g(img->color); + unsigned char b = _b(img->color); + int dst_stride = frame.GetWidth() * 3; + + unsigned char* src; + unsigned char* dst; + + src = img->bitmap; + dst = frame.GetData() + img->dst_y * dst_stride + img->dst_x * 3; + for (int y = 0; y < img->h; ++y) { + for (int x = 0; x < img->w; ++x) { + unsigned k = ((unsigned)src[x]) * opacity / 255; + // possible endianness problems + dst[x*3] = (k*r + (255-k)*dst[x*3]) / 255; + dst[x*3+1] = (k*g + (255-k)*dst[x*3+1]) / 255; + dst[x*3+2] = (k*b + (255-k)*dst[x*3+2]) / 255; + } + src += img->stride; + dst += dst_stride; + } +} + +static void blend(wxImage &frame, ass_image_t* img) { + int cnt = 0; + while (img) { + blend_single(frame, img); + ++cnt; + img = img->next; + } +} + +void SubtitleProviderLibASS::Render(wxImage &frame, int ms) +{ + wxString text = subs->GetString(); + if (text != last_sub) { // almost always true because of "Video Position" header + if (ass_track) + ass_free_track(ass_track); + ass_track = ass_read_memory(ass_library, ((char*)text.GetData()) + 4, sizeof(wchar_t) * text.Length() - 4, "UCS-4LE"); + } + + if (!ass_track) + throw _T("libass parse error"); + + ass_image_t* img = ass_render_frame(ass_renderer, ass_track, ms); + blend(frame, img); +} + +void SubtitleProviderLibASS::Unbind() +{ + if (vpro) + vpro->AttachOverlay(NULL); + vpro = NULL; +} + +#endif /* HAVE_LIBASS */ diff --git a/core/video_provider_lavc.cpp b/core/video_provider_lavc.cpp index 70ab51820..3cbfd2164 100644 --- a/core/video_provider_lavc.cpp +++ b/core/video_provider_lavc.cpp @@ -73,7 +73,7 @@ LAVCVideoProvider::LAVCVideoProvider(wxString filename, wxString subfilename) { // Attach subtitles try { - SubtitleProvider::Class::GetProvider(_T("asa"), AssFile::top)->Bind(this); + SubtitleProvider::Class::GetProvider(_T("libass"), AssFile::top)->Bind(this); } catch (...) { /* warn user? */ }