mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-01 10:13:22 +00:00
Merge branch 'unicode-text'
# Conflicts: # third_party/libpng # third_party/zlib
This commit is contained in:
commit
8028cf64db
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
@ -33,7 +33,6 @@
|
||||
#include "doc/palette.h"
|
||||
#include "gfx/border.h"
|
||||
#include "gfx/region.h"
|
||||
#include "she/scoped_surface_lock.h"
|
||||
#include "she/surface.h"
|
||||
#include "she/system.h"
|
||||
#include "ui/button.h"
|
||||
@ -457,8 +456,7 @@ she::Surface* BrushPopup::createSurfaceForBrush(const BrushRef& origBrush)
|
||||
delete palette;
|
||||
}
|
||||
else {
|
||||
she::ScopedSurfaceLock lock(surface);
|
||||
lock->clear();
|
||||
surface->clear();
|
||||
}
|
||||
|
||||
return surface;
|
||||
|
@ -360,7 +360,7 @@ void FileList::onPaint(ui::PaintEvent& ev)
|
||||
if (fi->isFolder()) {
|
||||
int icon_w = font()->textLength("[+]");
|
||||
|
||||
g->drawUIString("[+]", fgcolor, bgcolor, gfx::Point(x, y+2*guiscale()));
|
||||
g->drawString("[+]", fgcolor, bgcolor, gfx::Point(x, y+2*guiscale()));
|
||||
x += icon_w+2*guiscale();
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
@ -33,7 +33,6 @@
|
||||
#include "gfx/rect.h"
|
||||
#include "gfx/size.h"
|
||||
#include "she/font.h"
|
||||
#include "she/scoped_surface_lock.h"
|
||||
#include "she/surface.h"
|
||||
#include "she/system.h"
|
||||
#include "ui/intern.h"
|
||||
@ -504,9 +503,9 @@ she::Surface* SkinTheme::sliceSheet(she::Surface* sur, const gfx::Rect& bounds)
|
||||
sur = she::instance()->createRgbaSurface(bounds.w, bounds.h);
|
||||
|
||||
{
|
||||
she::ScopedSurfaceLock src(m_sheet);
|
||||
she::ScopedSurfaceLock dst(sur);
|
||||
src->blitTo(dst, bounds.x, bounds.y, 0, 0, bounds.w, bounds.h);
|
||||
she::SurfaceLock lockSrc(m_sheet);
|
||||
she::SurfaceLock lockDst(sur);
|
||||
m_sheet->blitTo(sur, bounds.x, bounds.y, 0, 0, bounds.w, bounds.h);
|
||||
}
|
||||
|
||||
sur->applyScale(guiscale());
|
||||
@ -959,7 +958,7 @@ void SkinTheme::paintEntry(PaintEvent& ev)
|
||||
}
|
||||
|
||||
w = g->measureChar(ch).w;
|
||||
if (x+w > bounds.x2()-widget->childSpacing()*guiscale())
|
||||
if (x+w > bounds.x2())
|
||||
return;
|
||||
|
||||
caret_x = x;
|
||||
@ -2017,7 +2016,7 @@ she::Font* SkinTheme::loadFont(const std::string& userFont, const std::string& t
|
||||
// Try to load the font
|
||||
while (rf.next()) {
|
||||
try {
|
||||
she::Font* f = she::instance()->loadBitmapFont(rf.filename().c_str(), guiscale());
|
||||
she::Font* f = she::instance()->loadSpriteSheetFont(rf.filename().c_str(), guiscale());
|
||||
if (f->isScalable())
|
||||
f->setSize(8);
|
||||
return f;
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "app/ui/skin/style.h"
|
||||
#include "she/font.h"
|
||||
#include "she/scoped_surface_lock.h"
|
||||
#include "she/surface.h"
|
||||
#include "she/system.h"
|
||||
#include "ui/intern.h"
|
||||
@ -918,11 +917,11 @@ void Tabs::createFloatingOverlay(Tab* tab)
|
||||
|
||||
// Fill the surface with pink color
|
||||
{
|
||||
she::ScopedSurfaceLock lock(surface);
|
||||
she::SurfaceLock lock(surface);
|
||||
#ifdef USE_ALLEG4_BACKEND
|
||||
lock->fillRect(gfx::rgba(255, 0, 255), gfx::Rect(0, 0, surface->width(), surface->height()));
|
||||
surface->fillRect(gfx::rgba(255, 0, 255), gfx::Rect(0, 0, surface->width(), surface->height()));
|
||||
#else
|
||||
lock->fillRect(gfx::rgba(0, 0, 0, 0), gfx::Rect(0, 0, surface->width(), surface->height()));
|
||||
surface->fillRect(gfx::rgba(0, 0, 0, 0), gfx::Rect(0, 0, surface->width(), surface->height()));
|
||||
#endif
|
||||
}
|
||||
{
|
||||
@ -933,16 +932,16 @@ void Tabs::createFloatingOverlay(Tab* tab)
|
||||
#ifdef USE_ALLEG4_BACKEND
|
||||
// Make pink parts transparent (TODO remove this hack when we change the back-end to Skia)
|
||||
{
|
||||
she::ScopedSurfaceLock lock(surface);
|
||||
she::SurfaceLock lock(surface);
|
||||
|
||||
for (int y=0; y<surface->height(); ++y)
|
||||
for (int x=0; x<surface->width(); ++x) {
|
||||
gfx::Color c = lock->getPixel(x, y);
|
||||
gfx::Color c = surface->getPixel(x, y);
|
||||
c = (c != gfx::rgba(255, 0, 255, 0) &&
|
||||
c != gfx::rgba(255, 0, 255, 255) ?
|
||||
gfx::rgba(gfx::getr(c), gfx::getg(c), gfx::getb(c), 255):
|
||||
gfx::ColorNone);
|
||||
lock->putPixel(c, x, y);
|
||||
surface->putPixel(c, x, y);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -11,131 +11,52 @@
|
||||
|
||||
#include "app/util/freetype_utils.h"
|
||||
|
||||
#include "base/string.h"
|
||||
#include "base/unique_ptr.h"
|
||||
#include "doc/blend_funcs.h"
|
||||
#include "doc/blend_internals.h"
|
||||
#include "doc/color.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/primitives.h"
|
||||
#include "ft/face.h"
|
||||
#include "ft/lib.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "freetype/ftglyph.h"
|
||||
#include "ft2build.h"
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
namespace app {
|
||||
|
||||
template<typename Iterator, typename Func>
|
||||
static void for_each_glyph(FT_Face face, bool antialias,
|
||||
Iterator first, Iterator end,
|
||||
Func callback)
|
||||
{
|
||||
bool use_kerning = (FT_HAS_KERNING(face) ? true: false);
|
||||
|
||||
// Calculate size
|
||||
FT_UInt prev_glyph = 0;
|
||||
int x = 0;
|
||||
for (; first != end; ++first) {
|
||||
FT_UInt glyph_index = FT_Get_Char_Index(face, *first);
|
||||
|
||||
if (use_kerning && prev_glyph && glyph_index) {
|
||||
FT_Vector kerning;
|
||||
FT_Get_Kerning(face, prev_glyph, glyph_index,
|
||||
FT_KERNING_DEFAULT, &kerning);
|
||||
x += kerning.x >> 6;
|
||||
}
|
||||
|
||||
FT_Error err = FT_Load_Glyph(
|
||||
face, glyph_index,
|
||||
FT_LOAD_RENDER |
|
||||
FT_LOAD_NO_BITMAP |
|
||||
(antialias ? FT_LOAD_TARGET_NORMAL:
|
||||
FT_LOAD_TARGET_MONO));
|
||||
|
||||
if (!err) {
|
||||
callback(x, face->glyph);
|
||||
x += face->glyph->advance.x >> 6;
|
||||
}
|
||||
|
||||
prev_glyph = glyph_index;
|
||||
}
|
||||
}
|
||||
|
||||
class ScopedFTLib {
|
||||
public:
|
||||
ScopedFTLib(FT_Library& ft) : m_ft(ft) {
|
||||
FT_Init_FreeType(&m_ft);
|
||||
}
|
||||
~ScopedFTLib() {
|
||||
FT_Done_FreeType(m_ft);
|
||||
}
|
||||
private:
|
||||
FT_Library& m_ft;
|
||||
};
|
||||
|
||||
class ScopedFTFace {
|
||||
public:
|
||||
ScopedFTFace(FT_Face& face) : m_face(face) {
|
||||
}
|
||||
~ScopedFTFace() {
|
||||
FT_Done_Face(m_face);
|
||||
}
|
||||
private:
|
||||
FT_Face& m_face;
|
||||
};
|
||||
|
||||
doc::Image* render_text(const std::string& fontfile, int fontsize,
|
||||
const std::string& text,
|
||||
doc::color_t color,
|
||||
bool antialias)
|
||||
{
|
||||
base::UniquePtr<doc::Image> image(nullptr);
|
||||
FT_Library ft;
|
||||
ScopedFTLib init_and_done_ft(ft);
|
||||
|
||||
FT_Open_Args args;
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.flags = FT_OPEN_PATHNAME;
|
||||
args.pathname = (FT_String*)fontfile.c_str();
|
||||
|
||||
FT_Face face;
|
||||
FT_Error err = FT_Open_Face(ft, &args, 0, &face);
|
||||
if (!err) {
|
||||
ScopedFTFace done_face(face);
|
||||
ft::Lib ft;
|
||||
|
||||
ft::Face face(ft.open(fontfile));
|
||||
if (face.isValid()) {
|
||||
// Set font size
|
||||
FT_Set_Pixel_Sizes(face, fontsize, fontsize);
|
||||
face.setSize(fontsize);
|
||||
face.setAntialias(antialias);
|
||||
|
||||
// Calculate text size
|
||||
base::utf8_const_iterator begin(text.begin()), end(text.end());
|
||||
gfx::Rect bounds(0, 0, 0, 0);
|
||||
for_each_glyph(
|
||||
face, antialias, begin, end,
|
||||
[&bounds](int x, FT_GlyphSlot glyph) {
|
||||
bounds |= gfx::Rect(x + glyph->bitmap_left,
|
||||
-glyph->bitmap_top,
|
||||
(int)glyph->bitmap.width,
|
||||
(int)glyph->bitmap.rows);
|
||||
});
|
||||
gfx::Rect bounds = face.calcTextBounds(text);
|
||||
|
||||
// Render the image and copy it to the clipboard
|
||||
if (!bounds.isEmpty()) {
|
||||
image.reset(doc::Image::create(doc::IMAGE_RGB, bounds.w, bounds.h));
|
||||
doc::clear_image(image, 0);
|
||||
|
||||
for_each_glyph(
|
||||
face, antialias, begin, end,
|
||||
[&bounds, &image, color, antialias](int x, FT_GlyphSlot glyph) {
|
||||
int t, yimg = - bounds.y - glyph->bitmap_top;
|
||||
face.forEachGlyph(
|
||||
text,
|
||||
[&bounds, &image, color, antialias](const ft::Glyph& glyph) {
|
||||
int t, yimg = - bounds.y + int(glyph.y);
|
||||
|
||||
for (int v=0; v<(int)glyph->bitmap.rows; ++v, ++yimg) {
|
||||
const uint8_t* p = glyph->bitmap.buffer + v*glyph->bitmap.pitch;
|
||||
int ximg = x - bounds.x + glyph->bitmap_left;
|
||||
for (int v=0; v<int(glyph.bitmap->rows); ++v, ++yimg) {
|
||||
const uint8_t* p = glyph.bitmap->buffer + v*glyph.bitmap->pitch;
|
||||
int ximg = - bounds.x + int(glyph.x);
|
||||
int bit = 0;
|
||||
|
||||
for (int u=0; u<(int)glyph->bitmap.width; ++u, ++ximg) {
|
||||
for (int u=0; u<int(glyph.bitmap->width); ++u, ++ximg) {
|
||||
int alpha;
|
||||
|
||||
if (antialias) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2001-2015 David Capello
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -18,7 +18,6 @@
|
||||
#include "doc/rgbmap.h"
|
||||
#include "she/surface.h"
|
||||
#include "she/surface_format.h"
|
||||
#include "she/scoped_surface_lock.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
@ -71,7 +70,7 @@ uint32_t convert_color_to_surface<BitmapTraits, she::kRgbaSurfaceFormat>(color_t
|
||||
}
|
||||
|
||||
template<typename ImageTraits, typename AddressType>
|
||||
void convert_image_to_surface_templ(const Image* image, she::LockedSurface* dst,
|
||||
void convert_image_to_surface_templ(const Image* image, she::Surface* dst,
|
||||
int src_x, int src_y, int dst_x, int dst_y, int w, int h, const Palette* palette, const she::SurfaceFormatData* fd)
|
||||
{
|
||||
const LockImageBits<ImageTraits> bits(image, gfx::Rect(src_x, src_y, w, h));
|
||||
@ -105,7 +104,7 @@ struct Address24bpp
|
||||
};
|
||||
|
||||
template<typename ImageTraits>
|
||||
void convert_image_to_surface_selector(const Image* image, she::LockedSurface* surface,
|
||||
void convert_image_to_surface_selector(const Image* image, she::Surface* surface,
|
||||
int src_x, int src_y, int dst_x, int dst_y, int w, int h, const Palette* palette, const she::SurfaceFormatData* fd)
|
||||
{
|
||||
switch (fd->bitsPerPixel) {
|
||||
@ -156,26 +155,26 @@ void convert_image_to_surface(const Image* image, const Palette* palette,
|
||||
w = dstBounds.w;
|
||||
h = dstBounds.h;
|
||||
|
||||
she::ScopedSurfaceLock dst(surface);
|
||||
she::SurfaceLock lockDst(surface);
|
||||
she::SurfaceFormatData fd;
|
||||
dst->getFormat(&fd);
|
||||
surface->getFormat(&fd);
|
||||
|
||||
switch (image->pixelFormat()) {
|
||||
|
||||
case IMAGE_RGB:
|
||||
convert_image_to_surface_selector<RgbTraits>(image, dst, src_x, src_y, dst_x, dst_y, w, h, palette, &fd);
|
||||
convert_image_to_surface_selector<RgbTraits>(image, surface, src_x, src_y, dst_x, dst_y, w, h, palette, &fd);
|
||||
break;
|
||||
|
||||
case IMAGE_GRAYSCALE:
|
||||
convert_image_to_surface_selector<GrayscaleTraits>(image, dst, src_x, src_y, dst_x, dst_y, w, h, palette, &fd);
|
||||
convert_image_to_surface_selector<GrayscaleTraits>(image, surface, src_x, src_y, dst_x, dst_y, w, h, palette, &fd);
|
||||
break;
|
||||
|
||||
case IMAGE_INDEXED:
|
||||
convert_image_to_surface_selector<IndexedTraits>(image, dst, src_x, src_y, dst_x, dst_y, w, h, palette, &fd);
|
||||
convert_image_to_surface_selector<IndexedTraits>(image, surface, src_x, src_y, dst_x, dst_y, w, h, palette, &fd);
|
||||
break;
|
||||
|
||||
case IMAGE_BITMAP:
|
||||
convert_image_to_surface_selector<BitmapTraits>(image, dst, src_x, src_y, dst_x, dst_y, w, h, palette, &fd);
|
||||
convert_image_to_surface_selector<BitmapTraits>(image, surface, src_x, src_y, dst_x, dst_y, w, h, palette, &fd);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
20
src/ft/LICENSE.txt
Normal file
20
src/ft/LICENSE.txt
Normal file
@ -0,0 +1,20 @@
|
||||
Copyright (c) 2016 David Capello
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
4
src/ft/README.md
Normal file
4
src/ft/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Aseprite FreeType Wrapper
|
||||
*Copyright (C) 2016 David Capello*
|
||||
|
||||
> Distributed under [MIT license](LICENSE.txt)
|
257
src/ft/face.h
Normal file
257
src/ft/face.h
Normal file
@ -0,0 +1,257 @@
|
||||
// Aseprite FreeType Wrapper
|
||||
// Copyright (c) 2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef FT_FACE_H_INCLUDED
|
||||
#define FT_FACE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "base/disable_copying.h"
|
||||
#include "base/string.h"
|
||||
#include "ft/freetype_headers.h"
|
||||
#include "gfx/rect.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace ft {
|
||||
|
||||
struct Glyph {
|
||||
FT_UInt glyph_index;
|
||||
FT_Glyph ft_glyph;
|
||||
FT_Bitmap* bitmap;
|
||||
double bearingX;
|
||||
double bearingY;
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
|
||||
template<typename Cache>
|
||||
class FaceBase {
|
||||
public:
|
||||
FaceBase(FT_Face face) : m_face(face) {
|
||||
}
|
||||
|
||||
~FaceBase() {
|
||||
if (m_face)
|
||||
FT_Done_Face(m_face);
|
||||
}
|
||||
|
||||
operator FT_Face() { return m_face; }
|
||||
FT_Face operator->() { return m_face; }
|
||||
|
||||
bool isValid() const {
|
||||
return (m_face != nullptr);
|
||||
}
|
||||
|
||||
bool antialias() const {
|
||||
return m_antialias;
|
||||
}
|
||||
|
||||
void setAntialias(bool antialias) {
|
||||
m_antialias = antialias;
|
||||
m_cache.invalidate();
|
||||
}
|
||||
|
||||
void setSize(int size) {
|
||||
FT_Set_Pixel_Sizes(m_face, size, size);
|
||||
m_cache.invalidate();
|
||||
}
|
||||
|
||||
double height() const {
|
||||
FT_Size_Metrics* metrics = &m_face->size->metrics;
|
||||
double em_size = 1.0 * m_face->units_per_EM;
|
||||
double y_scale = metrics->y_ppem / em_size;
|
||||
return int(m_face->height * y_scale) - 1;
|
||||
}
|
||||
|
||||
double ascender() const {
|
||||
FT_Size_Metrics* metrics = &m_face->size->metrics;
|
||||
double em_size = 1.0 * m_face->units_per_EM;
|
||||
double y_scale = metrics->y_ppem / em_size;
|
||||
return int(m_face->ascender * y_scale);
|
||||
}
|
||||
|
||||
double descender() const {
|
||||
FT_Size_Metrics* metrics = &m_face->size->metrics;
|
||||
double em_size = 1.0 * m_face->units_per_EM;
|
||||
double y_scale = metrics->y_ppem / em_size;
|
||||
return int(m_face->descender * y_scale);
|
||||
}
|
||||
|
||||
protected:
|
||||
FT_Face m_face;
|
||||
bool m_antialias;
|
||||
Cache m_cache;
|
||||
|
||||
private:
|
||||
DISABLE_COPYING(FaceBase);
|
||||
};
|
||||
|
||||
template<typename Cache>
|
||||
class FaceFT : public FaceBase<Cache> {
|
||||
public:
|
||||
using FaceBase<Cache>::m_face;
|
||||
using FaceBase<Cache>::m_cache;
|
||||
|
||||
FaceFT(FT_Face face)
|
||||
: FaceBase<Cache>(face) {
|
||||
}
|
||||
|
||||
template<typename Callback>
|
||||
void forEachGlyph(const std::string& str, Callback callback) {
|
||||
bool use_kerning = (FT_HAS_KERNING(this->m_face) ? true: false);
|
||||
FT_UInt prev_glyph = 0;
|
||||
double x = 0, y = 0;
|
||||
|
||||
auto it = base::utf8_const_iterator(str.begin());
|
||||
auto end = base::utf8_const_iterator(str.end());
|
||||
for (; it != end; ++it) {
|
||||
FT_UInt glyph_index = this->m_cache.getGlyphIndex(
|
||||
this->m_face, *it);
|
||||
|
||||
if (use_kerning && prev_glyph && glyph_index) {
|
||||
FT_Vector kerning;
|
||||
FT_Get_Kerning(this->m_face, prev_glyph, glyph_index,
|
||||
FT_KERNING_DEFAULT, &kerning);
|
||||
x += kerning.x / 64.0;
|
||||
}
|
||||
|
||||
Glyph* glyph = this->m_cache.loadGlyph(
|
||||
this->m_face, glyph_index, this->m_antialias);
|
||||
if (glyph) {
|
||||
glyph->bitmap = &FT_BitmapGlyph(glyph->ft_glyph)->bitmap;
|
||||
glyph->x = x + glyph->bearingX;
|
||||
glyph->y = y
|
||||
+ this->height()
|
||||
+ this->descender() // descender is negative
|
||||
- glyph->bearingY;
|
||||
|
||||
callback(*glyph);
|
||||
|
||||
x += glyph->ft_glyph->advance.x / double(1 << 16);
|
||||
y += glyph->ft_glyph->advance.y / double(1 << 16);
|
||||
|
||||
this->m_cache.doneGlyph(glyph);
|
||||
}
|
||||
|
||||
prev_glyph = glyph_index;
|
||||
}
|
||||
}
|
||||
|
||||
gfx::Rect calcTextBounds(const std::string& str) {
|
||||
gfx::Rect bounds(0, 0, 0, 0);
|
||||
|
||||
forEachGlyph(
|
||||
str,
|
||||
[&bounds, this](Glyph& glyph) {
|
||||
bounds |= gfx::Rect(int(glyph.x),
|
||||
int(glyph.y),
|
||||
glyph.bitmap->width,
|
||||
glyph.bitmap->rows);
|
||||
});
|
||||
|
||||
return bounds;
|
||||
}
|
||||
};
|
||||
|
||||
class NoCache {
|
||||
public:
|
||||
void invalidate() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
FT_UInt getGlyphIndex(FT_Face face, int charCode) {
|
||||
return FT_Get_Char_Index(face, charCode);
|
||||
}
|
||||
|
||||
Glyph* loadGlyph(FT_Face face, FT_UInt glyphIndex, bool antialias) {
|
||||
FT_Error err = FT_Load_Glyph(
|
||||
face, glyphIndex,
|
||||
FT_LOAD_RENDER |
|
||||
(antialias ? FT_LOAD_TARGET_NORMAL:
|
||||
FT_LOAD_TARGET_MONO));
|
||||
if (err)
|
||||
return nullptr;
|
||||
|
||||
FT_Glyph ft_glyph;
|
||||
err = FT_Get_Glyph(face->glyph, &ft_glyph);
|
||||
if (err)
|
||||
return nullptr;
|
||||
|
||||
if (ft_glyph->format != FT_GLYPH_FORMAT_BITMAP) {
|
||||
err = FT_Glyph_To_Bitmap(&ft_glyph, FT_RENDER_MODE_NORMAL, 0, 1);
|
||||
if (!err) {
|
||||
FT_Done_Glyph(ft_glyph);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
m_glyph.ft_glyph = ft_glyph;
|
||||
m_glyph.bearingX = face->glyph->metrics.horiBearingX / 64.0;
|
||||
m_glyph.bearingY = face->glyph->metrics.horiBearingY / 64.0;
|
||||
|
||||
return &m_glyph;
|
||||
}
|
||||
|
||||
void doneGlyph(Glyph* glyph) {
|
||||
ASSERT(glyph);
|
||||
FT_Done_Glyph(glyph->ft_glyph);
|
||||
}
|
||||
|
||||
private:
|
||||
Glyph m_glyph;
|
||||
};
|
||||
|
||||
class SimpleCache : public NoCache {
|
||||
public:
|
||||
~SimpleCache() {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void invalidate() {
|
||||
for (auto& it : m_glyphMap) {
|
||||
FT_Done_Glyph(it.second->ft_glyph);
|
||||
delete it.second;
|
||||
}
|
||||
|
||||
m_glyphMap.clear();
|
||||
}
|
||||
|
||||
Glyph* loadGlyph(FT_Face face, FT_UInt glyphIndex, bool antialias) {
|
||||
auto it = m_glyphMap.find(glyphIndex);
|
||||
if (it != m_glyphMap.end())
|
||||
return it->second;
|
||||
|
||||
Glyph* glyph = NoCache::loadGlyph(face, glyphIndex, antialias);
|
||||
if (!glyph)
|
||||
return nullptr;
|
||||
|
||||
FT_Glyph new_ft_glyph = nullptr;
|
||||
FT_Glyph_Copy(glyph->ft_glyph, &new_ft_glyph);
|
||||
if (!new_ft_glyph)
|
||||
return nullptr;
|
||||
|
||||
Glyph* newGlyph = new Glyph(*glyph);
|
||||
newGlyph->ft_glyph = new_ft_glyph;
|
||||
|
||||
m_glyphMap[glyphIndex] = newGlyph;
|
||||
FT_Done_Glyph(glyph->ft_glyph);
|
||||
|
||||
return newGlyph;
|
||||
}
|
||||
|
||||
void doneGlyph(Glyph* glyph) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<FT_UInt, Glyph*> m_glyphMap;
|
||||
};
|
||||
|
||||
typedef FaceFT<SimpleCache> Face;
|
||||
|
||||
} // namespace ft
|
||||
|
||||
#endif
|
15
src/ft/freetype_headers.h
Normal file
15
src/ft/freetype_headers.h
Normal file
@ -0,0 +1,15 @@
|
||||
// Aseprite FreeType Wrapper
|
||||
// Copyright (c) 2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef FT_FREETYPE_HEADERS_H_INCLUDED
|
||||
#define FT_FREETYPE_HEADERS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "freetype/ftglyph.h"
|
||||
#include "ft2build.h"
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#endif
|
54
src/ft/lib.h
Normal file
54
src/ft/lib.h
Normal file
@ -0,0 +1,54 @@
|
||||
// Aseprite FreeType Wrapper
|
||||
// Copyright (c) 2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef FT_LIB_H_INCLUDED
|
||||
#define FT_LIB_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "base/disable_copying.h"
|
||||
#include "ft/freetype_headers.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace ft {
|
||||
|
||||
class Lib {
|
||||
public:
|
||||
Lib() : m_ft(nullptr) {
|
||||
FT_Init_FreeType(&m_ft);
|
||||
}
|
||||
|
||||
~Lib() {
|
||||
if (m_ft)
|
||||
FT_Done_FreeType(m_ft);
|
||||
}
|
||||
|
||||
operator FT_Library() {
|
||||
return m_ft;
|
||||
}
|
||||
|
||||
FT_Face open(const std::string& filename) {
|
||||
FT_Open_Args args;
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.flags = FT_OPEN_PATHNAME;
|
||||
args.pathname = (FT_String*)filename.c_str();
|
||||
|
||||
FT_Face face = nullptr;
|
||||
FT_Error err = FT_Open_Face(m_ft, &args, 0, &face);
|
||||
if (!err)
|
||||
FT_Select_Charmap(face, FT_ENCODING_UNICODE);
|
||||
return face;
|
||||
}
|
||||
|
||||
private:
|
||||
FT_Library m_ft;
|
||||
|
||||
DISABLE_COPYING(Lib);
|
||||
};
|
||||
|
||||
} // namespace ft
|
||||
|
||||
#endif
|
@ -1,7 +1,8 @@
|
||||
# SHE
|
||||
# Copyright (C) 2012-2016 David Capello
|
||||
|
||||
set(SHE_SOURCES)
|
||||
set(SHE_SOURCES
|
||||
common/freetype_font.cpp)
|
||||
|
||||
######################################################################
|
||||
# Allegro 4 backend
|
||||
@ -225,7 +226,8 @@ add_library(she ${SHE_SOURCES})
|
||||
|
||||
target_link_libraries(she
|
||||
gfx-lib
|
||||
base-lib)
|
||||
base-lib
|
||||
${FREETYPE_LIBRARY})
|
||||
|
||||
if(USE_ALLEG4_BACKEND)
|
||||
target_link_libraries(she
|
||||
|
@ -477,9 +477,9 @@ void Alleg4Display::recreateSurface()
|
||||
m_surface = newSurface;
|
||||
}
|
||||
|
||||
NonDisposableSurface* Alleg4Display::getSurface()
|
||||
Surface* Alleg4Display::getSurface()
|
||||
{
|
||||
return static_cast<NonDisposableSurface*>(m_surface);
|
||||
return m_surface;
|
||||
}
|
||||
|
||||
void Alleg4Display::flip(const gfx::Rect& bounds)
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
// Copyright (C) 2012-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -27,7 +27,7 @@ namespace she {
|
||||
int scale() const override;
|
||||
void setScale(int scale) override;
|
||||
void recreateSurface();
|
||||
NonDisposableSurface* getSurface() override;
|
||||
Surface* getSurface() override;
|
||||
void flip(const gfx::Rect& bounds) override;
|
||||
void maximize() override;
|
||||
bool isMaximized() const override;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
// Copyright (C) 2012-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -80,23 +80,27 @@ inline gfx::Color from_allegro(int color_depth, int color)
|
||||
Alleg4Surface::Alleg4Surface(BITMAP* bmp, DestroyFlag destroy)
|
||||
: m_bmp(bmp)
|
||||
, m_destroy(destroy)
|
||||
, m_lock(0)
|
||||
{
|
||||
}
|
||||
|
||||
Alleg4Surface::Alleg4Surface(int width, int height, DestroyFlag destroy)
|
||||
: m_bmp(create_bitmap(width, height))
|
||||
, m_destroy(destroy)
|
||||
, m_lock(0)
|
||||
{
|
||||
}
|
||||
|
||||
Alleg4Surface::Alleg4Surface(int width, int height, int bpp, DestroyFlag destroy)
|
||||
: m_bmp(create_bitmap_ex(bpp, width, height))
|
||||
, m_destroy(destroy)
|
||||
, m_lock(0)
|
||||
{
|
||||
}
|
||||
|
||||
Alleg4Surface::~Alleg4Surface()
|
||||
{
|
||||
ASSERT(m_lock == 0);
|
||||
if (m_destroy & DestroyHandle) {
|
||||
if (m_bmp)
|
||||
destroy_bitmap(m_bmp);
|
||||
@ -157,10 +161,18 @@ bool Alleg4Surface::intersectClipRect(const gfx::Rect& rc)
|
||||
m_bmp->ct < m_bmp->cb);
|
||||
}
|
||||
|
||||
LockedSurface* Alleg4Surface::lock()
|
||||
void Alleg4Surface::lock()
|
||||
{
|
||||
acquire_bitmap(m_bmp);
|
||||
return this;
|
||||
ASSERT(m_lock >= 0);
|
||||
if (m_lock++ == 0)
|
||||
acquire_bitmap(m_bmp);
|
||||
}
|
||||
|
||||
void Alleg4Surface::unlock()
|
||||
{
|
||||
ASSERT(m_lock > 0);
|
||||
if (--m_lock == 0)
|
||||
release_bitmap(m_bmp);
|
||||
}
|
||||
|
||||
void Alleg4Surface::setDrawMode(DrawMode mode, int param)
|
||||
@ -198,23 +210,6 @@ void* Alleg4Surface::nativeHandle()
|
||||
return reinterpret_cast<void*>(m_bmp);
|
||||
}
|
||||
|
||||
// LockedSurface implementation
|
||||
|
||||
int Alleg4Surface::lockedWidth() const
|
||||
{
|
||||
return m_bmp->w;
|
||||
}
|
||||
|
||||
int Alleg4Surface::lockedHeight() const
|
||||
{
|
||||
return m_bmp->h;
|
||||
}
|
||||
|
||||
void Alleg4Surface::unlock()
|
||||
{
|
||||
release_bitmap(m_bmp);
|
||||
}
|
||||
|
||||
void Alleg4Surface::clear()
|
||||
{
|
||||
clear_to_color(m_bmp, 0);
|
||||
@ -358,7 +353,7 @@ void Alleg4Surface::fillRect(gfx::Color color, const gfx::Rect& rc)
|
||||
solid_mode();
|
||||
}
|
||||
|
||||
void Alleg4Surface::blitTo(LockedSurface* dest, int srcx, int srcy, int dstx, int dsty, int width, int height) const
|
||||
void Alleg4Surface::blitTo(Surface* dest, int srcx, int srcy, int dstx, int dsty, int width, int height) const
|
||||
{
|
||||
ASSERT(m_bmp);
|
||||
ASSERT(dest);
|
||||
@ -379,12 +374,12 @@ void Alleg4Surface::scrollTo(const gfx::Rect& rc, int dx, int dy)
|
||||
rc.w, rc.h);
|
||||
}
|
||||
|
||||
void Alleg4Surface::drawSurface(const LockedSurface* src, int dstx, int dsty)
|
||||
void Alleg4Surface::drawSurface(const Surface* src, int dstx, int dsty)
|
||||
{
|
||||
draw_sprite(m_bmp, static_cast<const Alleg4Surface*>(src)->m_bmp, dstx, dsty);
|
||||
}
|
||||
|
||||
void Alleg4Surface::drawRgbaSurface(const LockedSurface* src, int dstx, int dsty)
|
||||
void Alleg4Surface::drawRgbaSurface(const Surface* src, int dstx, int dsty)
|
||||
{
|
||||
set_alpha_blender();
|
||||
draw_trans_sprite(m_bmp, static_cast<const Alleg4Surface*>(src)->m_bmp, dstx, dsty);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
// Copyright (C) 2012-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -11,12 +11,11 @@
|
||||
#include <allegro.h>
|
||||
|
||||
#include "she/surface.h"
|
||||
#include "she/common/locked_surface.h"
|
||||
#include "she/common/generic_surface.h"
|
||||
|
||||
namespace she {
|
||||
|
||||
class Alleg4Surface : public Surface
|
||||
, public CommonLockedSurface {
|
||||
class Alleg4Surface : public GenericDrawTextSurface<GenericDrawColoredRgbaSurface<Surface> > {
|
||||
public:
|
||||
enum DestroyFlag {
|
||||
None = 0,
|
||||
@ -38,15 +37,11 @@ namespace she {
|
||||
gfx::Rect getClipBounds() override;
|
||||
void setClipBounds(const gfx::Rect& rc) override;
|
||||
bool intersectClipRect(const gfx::Rect& rc) override;
|
||||
LockedSurface* lock() override;
|
||||
void lock() override;
|
||||
void unlock() override;
|
||||
void setDrawMode(DrawMode mode, int param) override;
|
||||
void applyScale(int scale) override;
|
||||
void* nativeHandle() override;
|
||||
|
||||
// LockedSurface implementation
|
||||
int lockedWidth() const override;
|
||||
int lockedHeight() const override;
|
||||
void unlock() override;
|
||||
void clear() override;
|
||||
uint8_t* getData(int x, int y) const override;
|
||||
void getFormat(SurfaceFormatData* formatData) const override;
|
||||
@ -57,14 +52,15 @@ namespace she {
|
||||
void drawLine(gfx::Color color, const gfx::Point& a, const gfx::Point& b) override;
|
||||
void drawRect(gfx::Color color, const gfx::Rect& rc) override;
|
||||
void fillRect(gfx::Color color, const gfx::Rect& rc) override;
|
||||
void blitTo(LockedSurface* dest, int srcx, int srcy, int dstx, int dsty, int width, int height) const override;
|
||||
void blitTo(Surface* dest, int srcx, int srcy, int dstx, int dsty, int width, int height) const override;
|
||||
void scrollTo(const gfx::Rect& rc, int dx, int dy) override;
|
||||
void drawSurface(const LockedSurface* src, int dstx, int dsty) override;
|
||||
void drawRgbaSurface(const LockedSurface* src, int dstx, int dsty) override;
|
||||
void drawSurface(const Surface* src, int dstx, int dsty) override;
|
||||
void drawRgbaSurface(const Surface* src, int dstx, int dsty) override;
|
||||
|
||||
private:
|
||||
BITMAP* m_bmp;
|
||||
DestroyFlag m_destroy;
|
||||
int m_lock;
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
89
src/she/common/freetype_font.cpp
Normal file
89
src/she/common/freetype_font.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "she/common/freetype_font.h"
|
||||
|
||||
#include "base/string.h"
|
||||
#include "gfx/point.h"
|
||||
#include "gfx/size.h"
|
||||
|
||||
namespace she {
|
||||
|
||||
FreeTypeFont::FreeTypeFont(const char* filename, int height)
|
||||
: m_face(m_ft.open(filename))
|
||||
{
|
||||
ASSERT(m_face.isValid());
|
||||
if (m_face.isValid())
|
||||
m_face.setSize(height);
|
||||
}
|
||||
|
||||
FreeTypeFont::~FreeTypeFont()
|
||||
{
|
||||
}
|
||||
|
||||
bool FreeTypeFont::isValid() const
|
||||
{
|
||||
return m_face.isValid();
|
||||
}
|
||||
|
||||
void FreeTypeFont::dispose()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
FontType FreeTypeFont::type()
|
||||
{
|
||||
return FontType::kTrueType;
|
||||
}
|
||||
|
||||
int FreeTypeFont::height() const
|
||||
{
|
||||
return int(m_face.height());
|
||||
}
|
||||
|
||||
int FreeTypeFont::charWidth(int chr) const
|
||||
{
|
||||
// TODO avoid creating a temporary string
|
||||
std::wstring tmp;
|
||||
tmp.push_back(chr);
|
||||
return m_face.calcTextBounds(base::to_utf8(tmp)).w;
|
||||
}
|
||||
|
||||
int FreeTypeFont::textLength(const std::string& str) const
|
||||
{
|
||||
return m_face.calcTextBounds(str).w;
|
||||
}
|
||||
|
||||
bool FreeTypeFont::isScalable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void FreeTypeFont::setSize(int size)
|
||||
{
|
||||
m_face.setSize(size);
|
||||
}
|
||||
|
||||
void FreeTypeFont::setAntialias(bool antialias)
|
||||
{
|
||||
m_face.setAntialias(antialias);
|
||||
}
|
||||
|
||||
FreeTypeFont* loadFreeTypeFont(const char* filename, int height)
|
||||
{
|
||||
FreeTypeFont* font = new FreeTypeFont(filename, height);
|
||||
if (!font->isValid()) {
|
||||
delete font;
|
||||
font = nullptr;
|
||||
}
|
||||
return font;
|
||||
}
|
||||
|
||||
} // namespace she
|
44
src/she/common/freetype_font.h
Normal file
44
src/she/common/freetype_font.h
Normal file
@ -0,0 +1,44 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_COMMON_FREETYPE_FONT_H_INCLUDED
|
||||
#define SHE_COMMON_FREETYPE_FONT_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "ft/face.h"
|
||||
#include "ft/lib.h"
|
||||
#include "she/font.h"
|
||||
|
||||
namespace she {
|
||||
class Font;
|
||||
|
||||
class FreeTypeFont : public Font {
|
||||
public:
|
||||
FreeTypeFont(const char* filename, int height);
|
||||
~FreeTypeFont();
|
||||
|
||||
bool isValid() const;
|
||||
void dispose() override;
|
||||
FontType type() override;
|
||||
int height() const override;
|
||||
int charWidth(int chr) const override;
|
||||
int textLength(const std::string& str) const override;
|
||||
bool isScalable() const override;
|
||||
void setSize(int size) override;
|
||||
void setAntialias(bool antialias) override;
|
||||
|
||||
ft::Face& face() { return m_face; }
|
||||
|
||||
private:
|
||||
mutable ft::Lib m_ft;
|
||||
mutable ft::Face m_face;
|
||||
};
|
||||
|
||||
FreeTypeFont* loadFreeTypeFont(const char* filename, int height);
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
236
src/she/common/generic_surface.h
Normal file
236
src/she/common/generic_surface.h
Normal file
@ -0,0 +1,236 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_COMMON_GENERIC_SURFACE_H
|
||||
#define SHE_COMMON_GENERIC_SURFACE_H
|
||||
#pragma once
|
||||
|
||||
#include "gfx/clip.h"
|
||||
#include "she/common/freetype_font.h"
|
||||
#include "she/common/sprite_sheet_font.h"
|
||||
|
||||
namespace she {
|
||||
|
||||
namespace {
|
||||
|
||||
#define MUL_UN8(a, b, t) \
|
||||
((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8))
|
||||
|
||||
gfx::Color blend(const gfx::Color backdrop, gfx::Color src)
|
||||
{
|
||||
if (gfx::geta(backdrop) == 0)
|
||||
return src;
|
||||
else if (gfx::geta(src) == 0)
|
||||
return backdrop;
|
||||
|
||||
int Br, Bg, Bb, Ba;
|
||||
int Sr, Sg, Sb, Sa;
|
||||
int Rr, Rg, Rb, Ra;
|
||||
|
||||
Br = gfx::getr(backdrop);
|
||||
Bg = gfx::getg(backdrop);
|
||||
Bb = gfx::getb(backdrop);
|
||||
Ba = gfx::geta(backdrop);
|
||||
|
||||
Sr = gfx::getr(src);
|
||||
Sg = gfx::getg(src);
|
||||
Sb = gfx::getb(src);
|
||||
Sa = gfx::geta(src);
|
||||
|
||||
int t;
|
||||
Ra = Ba + Sa - MUL_UN8(Ba, Sa, t);
|
||||
Rr = Br + (Sr-Br) * Sa / Ra;
|
||||
Rg = Bg + (Sg-Bg) * Sa / Ra;
|
||||
Rb = Bb + (Sb-Bb) * Sa / Ra;
|
||||
|
||||
return gfx::rgba(Rr, Rg, Rb, Ra);
|
||||
}
|
||||
|
||||
} // anoynmous namespace
|
||||
|
||||
template<typename Base>
|
||||
class GenericDrawColoredRgbaSurface : public Base {
|
||||
public:
|
||||
|
||||
void drawColoredRgbaSurface(const Surface* src, gfx::Color fg, gfx::Color bg, const gfx::Clip& clipbase) override {
|
||||
gfx::Clip clip(clipbase);
|
||||
if (!clip.clip(this->width(),
|
||||
this->height(),
|
||||
src->width(), src->height()))
|
||||
return;
|
||||
|
||||
SurfaceFormatData format;
|
||||
src->getFormat(&format);
|
||||
|
||||
ASSERT(format.format == kRgbaSurfaceFormat);
|
||||
ASSERT(format.bitsPerPixel == 32);
|
||||
|
||||
for (int v=0; v<clip.size.h; ++v) {
|
||||
const uint32_t* ptr = (const uint32_t*)src->getData(
|
||||
clip.src.x, clip.src.y+v);
|
||||
|
||||
for (int u=0; u<clip.size.w; ++u) {
|
||||
gfx::Color dstColor = this->getPixel(clip.dst.x+u, clip.dst.y+v);
|
||||
if (gfx::geta(bg) > 0)
|
||||
dstColor = blend(dstColor, bg);
|
||||
|
||||
uint32_t src = (((*ptr) & format.alphaMask) >> format.alphaShift);
|
||||
if (src > 0) {
|
||||
src = gfx::rgba(gfx::getr(fg),
|
||||
gfx::getg(fg),
|
||||
gfx::getb(fg), src);
|
||||
dstColor = blend(dstColor, src);
|
||||
}
|
||||
|
||||
this->putPixel(dstColor, clip.dst.x+u, clip.dst.y+v);
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Base>
|
||||
class GenericDrawTextSurface : public Base {
|
||||
public:
|
||||
|
||||
void drawChar(Font* font, gfx::Color fg, gfx::Color bg, int x, int y, int chr) override {
|
||||
switch (font->type()) {
|
||||
|
||||
case FontType::kSpriteSheet: {
|
||||
SpriteSheetFont* ssFont = static_cast<SpriteSheetFont*>(font);
|
||||
|
||||
gfx::Rect charBounds = ssFont->getCharBounds(chr);
|
||||
if (!charBounds.isEmpty()) {
|
||||
Surface* sheet = ssFont->getSurfaceSheet();
|
||||
SurfaceLock lock(sheet);
|
||||
this->drawColoredRgbaSurface(sheet, fg, bg, gfx::Clip(x, y, charBounds));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case FontType::kTrueType: {
|
||||
// TODO avoid a temporary string
|
||||
std::wstring str;
|
||||
str.push_back(chr);
|
||||
drawString(font, fg, bg, x, y, base::to_utf8(str).c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void drawString(Font* font, gfx::Color fg, gfx::Color bg, int x, int y, const std::string& str) override {
|
||||
switch (font->type()) {
|
||||
|
||||
case FontType::kSpriteSheet: {
|
||||
base::utf8_const_iterator it(str.begin()), end(str.end());
|
||||
while (it != end) {
|
||||
drawChar(font, fg, bg, x, y, *it);
|
||||
x += font->charWidth(*it);
|
||||
++it;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case FontType::kTrueType: {
|
||||
FreeTypeFont* ttFont = static_cast<FreeTypeFont*>(font);
|
||||
bool antialias = ttFont->face().antialias();
|
||||
int fg_alpha = gfx::geta(fg);
|
||||
|
||||
gfx::Rect clipBounds = this->getClipBounds();
|
||||
|
||||
she::SurfaceFormatData fd;
|
||||
this->getFormat(&fd);
|
||||
|
||||
ttFont->face().forEachGlyph(
|
||||
str,
|
||||
[this, x, y, fg, fg_alpha, bg, antialias, &clipBounds, &fd](const ft::Glyph& glyph) {
|
||||
gfx::Rect origDstBounds(x + int(glyph.x),
|
||||
y + int(glyph.y),
|
||||
int(glyph.bitmap->width),
|
||||
int(glyph.bitmap->rows));
|
||||
gfx::Rect dstBounds = origDstBounds;
|
||||
dstBounds &= clipBounds;
|
||||
if (dstBounds.isEmpty())
|
||||
return;
|
||||
|
||||
int clippedRows = dstBounds.y - origDstBounds.y;
|
||||
int dst_y = dstBounds.y;
|
||||
int t;
|
||||
for (int v=0; v<dstBounds.h; ++v, ++dst_y) {
|
||||
int bit = 0;
|
||||
const uint8_t* p = glyph.bitmap->buffer
|
||||
+ (v+clippedRows)*glyph.bitmap->pitch;
|
||||
int dst_x = dstBounds.x;
|
||||
uint32_t* dst_address =
|
||||
(uint32_t*)this->getData(dst_x, dst_y);
|
||||
|
||||
// Skip first clipped pixels
|
||||
for (int u=0; u<dstBounds.x-origDstBounds.x; ++u) {
|
||||
if (antialias) {
|
||||
++p;
|
||||
}
|
||||
else {
|
||||
if (bit == 8) {
|
||||
bit = 0;
|
||||
++p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int u=0; u<dstBounds.w; ++u, ++dst_x) {
|
||||
ASSERT(clipBounds.contains(gfx::Point(dst_x, dst_y)));
|
||||
|
||||
int alpha;
|
||||
if (antialias) {
|
||||
alpha = *(p++);
|
||||
}
|
||||
else {
|
||||
alpha = ((*p) & (1 << (7 - (bit++))) ? 255: 0);
|
||||
if (bit == 8) {
|
||||
bit = 0;
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t backdrop = *dst_address;
|
||||
gfx::Color backdropColor =
|
||||
gfx::rgba(
|
||||
((backdrop & fd.redMask) >> fd.redShift),
|
||||
((backdrop & fd.greenMask) >> fd.greenShift),
|
||||
((backdrop & fd.blueMask) >> fd.blueShift),
|
||||
((backdrop & fd.alphaMask) >> fd.alphaShift));
|
||||
|
||||
gfx::Color output = gfx::rgba(gfx::getr(fg),
|
||||
gfx::getg(fg),
|
||||
gfx::getb(fg),
|
||||
MUL_UN8(fg_alpha, alpha, t));
|
||||
if (gfx::geta(bg) > 0)
|
||||
output = blend(blend(backdropColor, bg), output);
|
||||
else
|
||||
output = blend(backdropColor, output);
|
||||
|
||||
*dst_address =
|
||||
((gfx::getr(output) << fd.redShift ) & fd.redMask ) |
|
||||
((gfx::getg(output) << fd.greenShift) & fd.greenMask) |
|
||||
((gfx::getb(output) << fd.blueShift ) & fd.blueMask ) |
|
||||
((gfx::geta(output) << fd.alphaShift) & fd.alphaMask);
|
||||
|
||||
++dst_address;
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
@ -1,115 +0,0 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_COMMON_LOCKED_SURFACE_H
|
||||
#define SHE_COMMON_LOCKED_SURFACE_H
|
||||
#pragma once
|
||||
|
||||
#include "gfx/clip.h"
|
||||
#include "she/common/font.h"
|
||||
#include "she/locked_surface.h"
|
||||
#include "she/scoped_surface_lock.h"
|
||||
|
||||
namespace she {
|
||||
|
||||
namespace {
|
||||
|
||||
#define MUL_UN8(a, b, t) \
|
||||
((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8))
|
||||
|
||||
gfx::Color blend(const gfx::Color backdrop, gfx::Color src)
|
||||
{
|
||||
if (gfx::geta(backdrop) == 0)
|
||||
return src;
|
||||
else if (gfx::geta(src) == 0)
|
||||
return backdrop;
|
||||
|
||||
int Br, Bg, Bb, Ba;
|
||||
int Sr, Sg, Sb, Sa;
|
||||
int Rr, Rg, Rb, Ra;
|
||||
|
||||
Br = gfx::getr(backdrop);
|
||||
Bg = gfx::getg(backdrop);
|
||||
Bb = gfx::getb(backdrop);
|
||||
Ba = gfx::geta(backdrop);
|
||||
|
||||
Sr = gfx::getr(src);
|
||||
Sg = gfx::getg(src);
|
||||
Sb = gfx::getb(src);
|
||||
Sa = gfx::geta(src);
|
||||
|
||||
int t;
|
||||
Ra = Ba + Sa - MUL_UN8(Ba, Sa, t);
|
||||
Rr = Br + (Sr-Br) * Sa / Ra;
|
||||
Rg = Bg + (Sg-Bg) * Sa / Ra;
|
||||
Rb = Bb + (Sb-Bb) * Sa / Ra;
|
||||
|
||||
return gfx::rgba(Rr, Rg, Rb, Ra);
|
||||
}
|
||||
|
||||
} // anoynmous namespace
|
||||
|
||||
class CommonLockedSurface : public LockedSurface {
|
||||
public:
|
||||
|
||||
void drawColoredRgbaSurface(const LockedSurface* src, gfx::Color fg, gfx::Color bg, const gfx::Clip& clipbase) override {
|
||||
gfx::Clip clip(clipbase);
|
||||
if (!clip.clip(lockedWidth(), lockedHeight(), src->lockedWidth(), src->lockedHeight()))
|
||||
return;
|
||||
|
||||
SurfaceFormatData format;
|
||||
src->getFormat(&format);
|
||||
|
||||
ASSERT(format.format == kRgbaSurfaceFormat);
|
||||
ASSERT(format.bitsPerPixel == 32);
|
||||
|
||||
for (int v=0; v<clip.size.h; ++v) {
|
||||
const uint32_t* ptr = (const uint32_t*)src->getData(
|
||||
clip.src.x, clip.src.y+v);
|
||||
|
||||
for (int u=0; u<clip.size.w; ++u) {
|
||||
gfx::Color dstColor = getPixel(clip.dst.x+u, clip.dst.y+v);
|
||||
if (gfx::geta(bg) > 0)
|
||||
dstColor = blend(dstColor, bg);
|
||||
|
||||
uint32_t src = (((*ptr) & format.alphaMask) >> format.alphaShift);
|
||||
if (src > 0) {
|
||||
src = gfx::rgba(gfx::getr(fg),
|
||||
gfx::getg(fg),
|
||||
gfx::getb(fg), src);
|
||||
dstColor = blend(dstColor, src);
|
||||
}
|
||||
|
||||
putPixel(dstColor, clip.dst.x+u, clip.dst.y+v);
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drawChar(Font* font, gfx::Color fg, gfx::Color bg, int x, int y, int chr) override {
|
||||
CommonFont* commonFont = static_cast<CommonFont*>(font);
|
||||
|
||||
gfx::Rect charBounds = commonFont->getCharBounds(chr);
|
||||
if (!charBounds.isEmpty()) {
|
||||
ScopedSurfaceLock lock(commonFont->getSurfaceSheet());
|
||||
drawColoredRgbaSurface(lock, fg, bg, gfx::Clip(x, y, charBounds));
|
||||
}
|
||||
}
|
||||
|
||||
void drawString(Font* font, gfx::Color fg, gfx::Color bg, int x, int y, const std::string& str) override {
|
||||
base::utf8_const_iterator it(str.begin()), end(str.end());
|
||||
while (it != end) {
|
||||
drawChar(font, fg, bg, x, y, *it);
|
||||
x += font->charWidth(*it);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
@ -4,29 +4,27 @@
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_COMMON_FONT_H
|
||||
#define SHE_COMMON_FONT_H
|
||||
#ifndef SHE_SPRITE_SHEET_FONT_H
|
||||
#define SHE_SPRITE_SHEET_FONT_H
|
||||
#pragma once
|
||||
|
||||
#include "base/debug.h"
|
||||
#include "base/string.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "she/font.h"
|
||||
#include "she/locked_surface.h"
|
||||
#include "she/scoped_surface_lock.h"
|
||||
#include "she/surface.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace she {
|
||||
|
||||
class CommonFont : public Font {
|
||||
class SpriteSheetFont : public Font {
|
||||
public:
|
||||
|
||||
CommonFont() : m_sheet(nullptr) {
|
||||
SpriteSheetFont() : m_sheet(nullptr) {
|
||||
}
|
||||
|
||||
~CommonFont() {
|
||||
~SpriteSheetFont() {
|
||||
ASSERT(m_sheet);
|
||||
m_sheet->dispose();
|
||||
}
|
||||
@ -35,6 +33,10 @@ public:
|
||||
delete this;
|
||||
}
|
||||
|
||||
FontType type() override {
|
||||
return FontType::kSpriteSheet;
|
||||
}
|
||||
|
||||
int height() const override {
|
||||
return getCharBounds(' ').h;
|
||||
}
|
||||
@ -61,6 +63,10 @@ public:
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
void setAntialias(bool antialias) override {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
Surface* getSurfaceSheet() const {
|
||||
return m_sheet;
|
||||
}
|
||||
@ -74,13 +80,13 @@ public:
|
||||
}
|
||||
|
||||
static Font* fromSurface(Surface* sur) {
|
||||
CommonFont* font = new CommonFont;
|
||||
SpriteSheetFont* font = new SpriteSheetFont;
|
||||
font->m_sheet = sur;
|
||||
|
||||
ScopedSurfaceLock surLock(sur);
|
||||
SurfaceLock lock(sur);
|
||||
gfx::Rect bounds(0, 0, 1, 1);
|
||||
|
||||
while (font->findChar(surLock, sur->width(), sur->height(), bounds)) {
|
||||
while (font->findChar(sur, sur->width(), sur->height(), bounds)) {
|
||||
font->m_chars.push_back(bounds);
|
||||
bounds.x += bounds.w;
|
||||
}
|
||||
@ -90,7 +96,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
bool findChar(const LockedSurface* sur, int width, int height, gfx::Rect& bounds) {
|
||||
bool findChar(const Surface* sur, int width, int height, gfx::Rect& bounds) {
|
||||
gfx::Color keyColor = sur->getPixel(0, 0);
|
||||
|
||||
while (sur->getPixel(bounds.x, bounds.y) == keyColor) {
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
// Copyright (C) 2012-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -22,7 +22,8 @@
|
||||
#include "she/native_dialogs.h"
|
||||
#endif
|
||||
|
||||
#include "she/common/font.h"
|
||||
#include "she/common/freetype_font.h"
|
||||
#include "she/common/sprite_sheet_font.h"
|
||||
|
||||
namespace she {
|
||||
|
||||
@ -76,16 +77,20 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
Font* loadBitmapFont(const char* filename, int scale) override {
|
||||
Font* loadSpriteSheetFont(const char* filename, int scale) override {
|
||||
Surface* sheet = loadRgbaSurface(filename);
|
||||
Font* font = nullptr;
|
||||
if (sheet) {
|
||||
sheet->applyScale(scale);
|
||||
font = CommonFont::fromSurface(sheet);
|
||||
font = SpriteSheetFont::fromSurface(sheet);
|
||||
}
|
||||
return font;
|
||||
}
|
||||
|
||||
Font* loadTrueTypeFont(const char* filename, int height) override {
|
||||
return loadFreeTypeFont(filename, height);
|
||||
}
|
||||
|
||||
private:
|
||||
NativeDialogs* m_nativeDialogs;
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
// Copyright (C) 2012-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -16,7 +16,6 @@
|
||||
|
||||
namespace she {
|
||||
|
||||
class NonDisposableSurface;
|
||||
class Surface;
|
||||
class Font;
|
||||
|
||||
@ -46,7 +45,7 @@ namespace she {
|
||||
|
||||
// Returns the main surface to draw into this display.
|
||||
// You must not dispose this surface.
|
||||
virtual NonDisposableSurface* getSurface() = 0;
|
||||
virtual Surface* getSurface() = 0;
|
||||
|
||||
// Flips all graphics in the surface to the real display.
|
||||
virtual void flip(const gfx::Rect& bounds) = 0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
// Copyright (C) 2012-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -12,15 +12,23 @@
|
||||
|
||||
namespace she {
|
||||
|
||||
enum class FontType {
|
||||
kUnknown,
|
||||
kSpriteSheet,
|
||||
kTrueType,
|
||||
};
|
||||
|
||||
class Font {
|
||||
public:
|
||||
virtual ~Font() { }
|
||||
virtual void dispose() = 0;
|
||||
virtual FontType type() = 0;
|
||||
virtual int height() const = 0;
|
||||
virtual int charWidth(int chr) const = 0;
|
||||
virtual int textLength(const std::string& str) const = 0;
|
||||
virtual bool isScalable() const = 0;
|
||||
virtual void setSize(int size) = 0;
|
||||
virtual void setAntialias(bool antialias) = 0;
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
@ -1,58 +0,0 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2013, 2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_LOCKED_SURFACE_H_INCLUDED
|
||||
#define SHE_LOCKED_SURFACE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "gfx/color.h"
|
||||
#include "gfx/fwd.h"
|
||||
#include "she/surface_format.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace gfx {
|
||||
class Clip;
|
||||
}
|
||||
|
||||
namespace she {
|
||||
|
||||
class Font;
|
||||
|
||||
class LockedSurface {
|
||||
public:
|
||||
virtual ~LockedSurface() { }
|
||||
virtual int lockedWidth() const = 0;
|
||||
virtual int lockedHeight() const = 0;
|
||||
virtual void unlock() = 0;
|
||||
virtual void clear() = 0;
|
||||
|
||||
virtual uint8_t* getData(int x, int y) const = 0;
|
||||
virtual void getFormat(SurfaceFormatData* formatData) const = 0;
|
||||
|
||||
virtual gfx::Color getPixel(int x, int y) const = 0;
|
||||
virtual void putPixel(gfx::Color color, int x, int y) = 0;
|
||||
|
||||
virtual void drawHLine(gfx::Color color, int x, int y, int w) = 0;
|
||||
virtual void drawVLine(gfx::Color color, int x, int y, int h) = 0;
|
||||
virtual void drawLine(gfx::Color color, const gfx::Point& a, const gfx::Point& b) = 0;
|
||||
|
||||
virtual void drawRect(gfx::Color color, const gfx::Rect& rc) = 0;
|
||||
virtual void fillRect(gfx::Color color, const gfx::Rect& rc) = 0;
|
||||
|
||||
virtual void blitTo(LockedSurface* dest, int srcx, int srcy, int dstx, int dsty, int width, int height) const = 0;
|
||||
virtual void scrollTo(const gfx::Rect& rc, int dx, int dy) = 0;
|
||||
virtual void drawSurface(const LockedSurface* src, int dstx, int dsty) = 0;
|
||||
virtual void drawRgbaSurface(const LockedSurface* src, int dstx, int dsty) = 0;
|
||||
virtual void drawColoredRgbaSurface(const LockedSurface* src, gfx::Color fg, gfx::Color bg, const gfx::Clip& clip) = 0;
|
||||
|
||||
virtual void drawChar(Font* font, gfx::Color fg, gfx::Color bg, int x, int y, int chr) = 0;
|
||||
virtual void drawString(Font* font, gfx::Color fg, gfx::Color bg, int x, int y, const std::string& str) = 0;
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
@ -1,29 +0,0 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2013 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef SHE_SCOPED_SURFACE_LOCK_H_INCLUDED
|
||||
#define SHE_SCOPED_SURFACE_LOCK_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "she/surface.h"
|
||||
#include "she/locked_surface.h"
|
||||
|
||||
namespace she {
|
||||
|
||||
class ScopedSurfaceLock {
|
||||
public:
|
||||
ScopedSurfaceLock(Surface* surface) : m_lock(surface->lock()) { }
|
||||
~ScopedSurfaceLock() { m_lock->unlock(); }
|
||||
|
||||
LockedSurface* operator->() { return m_lock; }
|
||||
operator LockedSurface*() { return m_lock; }
|
||||
private:
|
||||
LockedSurface* m_lock;
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
// Copyright (C) 2012-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -14,9 +14,7 @@
|
||||
#include "she/event.h"
|
||||
#include "she/event_queue.h"
|
||||
#include "she/font.h"
|
||||
#include "she/locked_surface.h"
|
||||
#include "she/scoped_handle.h"
|
||||
#include "she/scoped_surface_lock.h"
|
||||
#include "she/surface.h"
|
||||
#include "she/system.h"
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
// Copyright (C) 2012-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -100,9 +100,9 @@ void SkiaDisplay::setScale(int scale)
|
||||
m_window.setScale(scale);
|
||||
}
|
||||
|
||||
NonDisposableSurface* SkiaDisplay::getSurface()
|
||||
Surface* SkiaDisplay::getSurface()
|
||||
{
|
||||
return static_cast<NonDisposableSurface*>(m_surface);
|
||||
return m_surface;
|
||||
}
|
||||
|
||||
// Flips all graphics in the surface to the real display. Returns
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
// Copyright (C) 2012-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -39,7 +39,7 @@ public:
|
||||
|
||||
// Returns the main surface to draw into this display.
|
||||
// You must not dispose this surface.
|
||||
NonDisposableSurface* getSurface() override;
|
||||
Surface* getSurface() override;
|
||||
|
||||
// Flips all graphics in the surface to the real display.
|
||||
void flip(const gfx::Rect& bounds) override;
|
||||
|
@ -10,9 +10,8 @@
|
||||
|
||||
#include "base/exception.h"
|
||||
#include "gfx/clip.h"
|
||||
#include "she/common/font.h"
|
||||
#include "she/locked_surface.h"
|
||||
#include "she/scoped_surface_lock.h"
|
||||
#include "she/common/generic_surface.h"
|
||||
#include "she/common/sprite_sheet_font.h"
|
||||
|
||||
#include "SkBitmap.h"
|
||||
#include "SkCanvas.h"
|
||||
@ -32,17 +31,18 @@ inline SkIRect to_skia(const gfx::Rect& rc) {
|
||||
return SkIRect::MakeXYWH(rc.x, rc.y, rc.w, rc.h);
|
||||
}
|
||||
|
||||
class SkiaSurface : public NonDisposableSurface
|
||||
, public LockedSurface {
|
||||
class SkiaSurface : public GenericDrawTextSurface<Surface> {
|
||||
public:
|
||||
SkiaSurface() : m_surface(nullptr)
|
||||
, m_canvas(nullptr) {
|
||||
, m_canvas(nullptr)
|
||||
, m_lock(0) {
|
||||
}
|
||||
|
||||
SkiaSurface(SkSurface* surface)
|
||||
: m_surface(surface)
|
||||
, m_canvas(nullptr)
|
||||
, m_clip(0, 0, width(), height())
|
||||
, m_lock(0)
|
||||
{
|
||||
ASSERT(m_surface);
|
||||
if (m_surface)
|
||||
@ -50,6 +50,7 @@ public:
|
||||
}
|
||||
|
||||
~SkiaSurface() {
|
||||
ASSERT(m_lock == 0);
|
||||
if (!m_surface)
|
||||
delete m_canvas;
|
||||
}
|
||||
@ -160,9 +161,16 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
LockedSurface* lock() override {
|
||||
m_bitmap.lockPixels();
|
||||
return this;
|
||||
void lock() override {
|
||||
ASSERT(m_lock >= 0);
|
||||
if (m_lock++ == 0)
|
||||
m_bitmap.lockPixels();
|
||||
}
|
||||
|
||||
void unlock() override {
|
||||
ASSERT(m_lock > 0);
|
||||
if (--m_lock == 0)
|
||||
m_bitmap.unlockPixels();
|
||||
}
|
||||
|
||||
void applyScale(int scaleFactor) override {
|
||||
@ -191,20 +199,6 @@ public:
|
||||
return (void*)this;
|
||||
}
|
||||
|
||||
// LockedSurface impl
|
||||
|
||||
int lockedWidth() const override {
|
||||
return width();
|
||||
}
|
||||
|
||||
int lockedHeight() const override {
|
||||
return height();
|
||||
}
|
||||
|
||||
void unlock() override {
|
||||
m_bitmap.unlockPixels();
|
||||
}
|
||||
|
||||
void clear() override {
|
||||
m_canvas->clear(0);
|
||||
}
|
||||
@ -329,11 +323,12 @@ public:
|
||||
m_canvas->drawIRect(to_skia(rc), m_paint);
|
||||
}
|
||||
|
||||
void blitTo(LockedSurface* dest, int srcx, int srcy, int dstx, int dsty, int width, int height) const override {
|
||||
void blitTo(Surface* dest, int srcx, int srcy, int dstx, int dsty, int width, int height) const override {
|
||||
SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
|
||||
std::vector<uint32_t> pixels(width * height * 4);
|
||||
m_canvas->readPixels(info, (void*)&pixels[0], 4*width, srcx, srcy);
|
||||
((SkiaSurface*)dest)->m_canvas->writePixels(info, (void*)&pixels[0], 4*width, dstx, dsty);
|
||||
static_cast<SkiaSurface*>(dest)
|
||||
->m_canvas->writePixels(info, (void*)&pixels[0], 4*width, dstx, dsty);
|
||||
}
|
||||
|
||||
void scrollTo(const gfx::Rect& rc, int dx, int dy) override {
|
||||
@ -344,6 +339,7 @@ public:
|
||||
return;
|
||||
|
||||
if (m_surface) {
|
||||
SurfaceLock lock(this);
|
||||
blitTo(this, clip.src.x, clip.src.y, clip.dst.x, clip.dst.y, clip.size.w, clip.size.h);
|
||||
return;
|
||||
}
|
||||
@ -374,7 +370,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void drawSurface(const LockedSurface* src, int dstx, int dsty) override {
|
||||
void drawSurface(const Surface* src, int dstx, int dsty) override {
|
||||
gfx::Clip clip(dstx, dsty, 0, 0,
|
||||
((SkiaSurface*)src)->width(),
|
||||
((SkiaSurface*)src)->height());
|
||||
@ -393,7 +389,7 @@ public:
|
||||
SkCanvas::kStrict_SrcRectConstraint);
|
||||
}
|
||||
|
||||
void drawRgbaSurface(const LockedSurface* src, int dstx, int dsty) override {
|
||||
void drawRgbaSurface(const Surface* src, int dstx, int dsty) override {
|
||||
gfx::Clip clip(dstx, dsty, 0, 0,
|
||||
((SkiaSurface*)src)->width(),
|
||||
((SkiaSurface*)src)->height());
|
||||
@ -412,9 +408,9 @@ public:
|
||||
SkCanvas::kStrict_SrcRectConstraint);
|
||||
}
|
||||
|
||||
void drawColoredRgbaSurface(const LockedSurface* src, gfx::Color fg, gfx::Color bg, const gfx::Clip& clipbase) override {
|
||||
void drawColoredRgbaSurface(const Surface* src, gfx::Color fg, gfx::Color bg, const gfx::Clip& clipbase) override {
|
||||
gfx::Clip clip(clipbase);
|
||||
if (!clip.clip(lockedWidth(), lockedHeight(), src->lockedWidth(), src->lockedHeight()))
|
||||
if (!clip.clip(width(), height(), src->width(), src->height()))
|
||||
return;
|
||||
|
||||
SkRect srcRect = SkRect::Make(SkIRect::MakeXYWH(clip.src.x, clip.src.y, clip.size.w, clip.size.h));
|
||||
@ -440,25 +436,6 @@ public:
|
||||
SkCanvas::kStrict_SrcRectConstraint);
|
||||
}
|
||||
|
||||
void drawChar(Font* font, gfx::Color fg, gfx::Color bg, int x, int y, int chr) override {
|
||||
CommonFont* commonFont = static_cast<CommonFont*>(font);
|
||||
|
||||
gfx::Rect charBounds = commonFont->getCharBounds(chr);
|
||||
if (!charBounds.isEmpty()) {
|
||||
ScopedSurfaceLock lock(commonFont->getSurfaceSheet());
|
||||
drawColoredRgbaSurface(lock, fg, bg, gfx::Clip(x, y, charBounds));
|
||||
}
|
||||
}
|
||||
|
||||
void drawString(Font* font, gfx::Color fg, gfx::Color bg, int x, int y, const std::string& str) override {
|
||||
base::utf8_const_iterator it(str.begin()), end(str.end());
|
||||
while (it != end) {
|
||||
drawChar(font, fg, bg, x, y, *it);
|
||||
x += font->charWidth(*it);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
SkBitmap& bitmap() {
|
||||
return m_bitmap;
|
||||
}
|
||||
@ -484,6 +461,7 @@ private:
|
||||
SkCanvas* m_canvas;
|
||||
SkPaint m_paint;
|
||||
gfx::Rect m_clip;
|
||||
int m_lock;
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2013, 2015 David Capello
|
||||
// Copyright (C) 2012-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -8,11 +8,20 @@
|
||||
#define SHE_SURFACE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "gfx/color.h"
|
||||
#include "gfx/fwd.h"
|
||||
#include "she/surface_format.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace gfx {
|
||||
class Clip;
|
||||
}
|
||||
|
||||
namespace she {
|
||||
|
||||
class LockedSurface;
|
||||
class Font;
|
||||
class SurfaceLock;
|
||||
|
||||
enum class DrawMode {
|
||||
Solid,
|
||||
@ -34,16 +43,43 @@ namespace she {
|
||||
|
||||
virtual void setDrawMode(DrawMode mode, int param = 0) = 0;
|
||||
|
||||
virtual LockedSurface* lock() = 0;
|
||||
virtual void lock() = 0;
|
||||
virtual void unlock() = 0;
|
||||
|
||||
virtual void clear() = 0;
|
||||
|
||||
virtual uint8_t* getData(int x, int y) const = 0;
|
||||
virtual void getFormat(SurfaceFormatData* formatData) const = 0;
|
||||
|
||||
virtual gfx::Color getPixel(int x, int y) const = 0;
|
||||
virtual void putPixel(gfx::Color color, int x, int y) = 0;
|
||||
|
||||
virtual void drawHLine(gfx::Color color, int x, int y, int w) = 0;
|
||||
virtual void drawVLine(gfx::Color color, int x, int y, int h) = 0;
|
||||
virtual void drawLine(gfx::Color color, const gfx::Point& a, const gfx::Point& b) = 0;
|
||||
|
||||
virtual void drawRect(gfx::Color color, const gfx::Rect& rc) = 0;
|
||||
virtual void fillRect(gfx::Color color, const gfx::Rect& rc) = 0;
|
||||
|
||||
virtual void blitTo(Surface* dest, int srcx, int srcy, int dstx, int dsty, int width, int height) const = 0;
|
||||
virtual void scrollTo(const gfx::Rect& rc, int dx, int dy) = 0;
|
||||
virtual void drawSurface(const Surface* src, int dstx, int dsty) = 0;
|
||||
virtual void drawRgbaSurface(const Surface* src, int dstx, int dsty) = 0;
|
||||
virtual void drawColoredRgbaSurface(const Surface* src, gfx::Color fg, gfx::Color bg, const gfx::Clip& clip) = 0;
|
||||
|
||||
virtual void drawChar(Font* font, gfx::Color fg, gfx::Color bg, int x, int y, int chr) = 0;
|
||||
virtual void drawString(Font* font, gfx::Color fg, gfx::Color bg, int x, int y, const std::string& str) = 0;
|
||||
|
||||
virtual void applyScale(int scaleFactor) = 0;
|
||||
virtual void* nativeHandle() = 0;
|
||||
};
|
||||
|
||||
class NonDisposableSurface : public Surface {
|
||||
class SurfaceLock {
|
||||
public:
|
||||
virtual ~NonDisposableSurface() { }
|
||||
SurfaceLock(Surface* surface) : m_surface(surface) { m_surface->lock(); }
|
||||
~SurfaceLock() { m_surface->unlock(); }
|
||||
private:
|
||||
virtual void dispose() = 0;
|
||||
Surface* m_surface;
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
@ -46,7 +46,8 @@ namespace she {
|
||||
virtual Surface* createRgbaSurface(int width, int height) = 0;
|
||||
virtual Surface* loadSurface(const char* filename) = 0;
|
||||
virtual Surface* loadRgbaSurface(const char* filename) = 0;
|
||||
virtual Font* loadBitmapFont(const char* filename, int scale = 1) = 0;
|
||||
virtual Font* loadSpriteSheetFont(const char* filename, int scale = 1) = 0;
|
||||
virtual Font* loadTrueTypeFont(const char* filename, int height) = 0;
|
||||
virtual Clipboard* createClipboard() = 0;
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -102,29 +102,33 @@ void Entry::hideCaret()
|
||||
|
||||
void Entry::setCaretPos(int pos)
|
||||
{
|
||||
base::utf8_const_iterator utf8_begin = base::utf8_const_iterator(text().begin());
|
||||
auto utf8_begin = base::utf8_const_iterator(text().begin());
|
||||
auto utf8_end = base::utf8_const_iterator(text().end());
|
||||
int textlen = base::utf8_length(text());
|
||||
int x, c;
|
||||
|
||||
m_caret = pos;
|
||||
m_caret = MID(0, pos, textlen);
|
||||
|
||||
// Backward scroll
|
||||
if (m_caret < m_scroll)
|
||||
if (m_scroll > m_caret)
|
||||
m_scroll = m_caret;
|
||||
|
||||
// Forward scroll
|
||||
m_scroll--;
|
||||
do {
|
||||
x = bounds().x + border().left();
|
||||
for (c=++m_scroll; ; c++) {
|
||||
int ch = (c < textlen ? *(utf8_begin+c) : ' ');
|
||||
|
||||
--m_scroll;
|
||||
int c;
|
||||
while (true) {
|
||||
c = ++m_scroll;
|
||||
auto utf8_it = utf8_begin + MID(0, c, textlen);
|
||||
int x = bounds().x + border().left()
|
||||
- font()->charWidth(' '); // Space for the carret
|
||||
for (; utf8_it != utf8_end; ++c, ++utf8_it) {
|
||||
int ch = *utf8_it;
|
||||
x += font()->charWidth(ch);
|
||||
|
||||
if (x >= bounds().x2()-border().right())
|
||||
break;
|
||||
}
|
||||
} while (m_caret >= c);
|
||||
if (m_caret < c || utf8_it == utf8_end)
|
||||
break;
|
||||
}
|
||||
|
||||
m_timer.start();
|
||||
m_state = true;
|
||||
@ -322,8 +326,8 @@ bool Entry::onProcessMessage(Message* msg)
|
||||
case kMouseMoveMessage:
|
||||
if (hasCapture()) {
|
||||
gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position();
|
||||
base::utf8_const_iterator utf8_begin = base::utf8_const_iterator(text().begin());
|
||||
base::utf8_const_iterator utf8_end = base::utf8_const_iterator(text().end());
|
||||
auto utf8_begin = base::utf8_const_iterator(text().begin());
|
||||
auto utf8_end = base::utf8_const_iterator(text().end());
|
||||
int textlen = base::utf8_length(text());
|
||||
int c, x;
|
||||
|
||||
@ -342,10 +346,12 @@ bool Entry::onProcessMessage(Message* msg)
|
||||
// Forward scroll
|
||||
else if (mousePos.x >= bounds().x2()) {
|
||||
if (m_scroll < textlen - getAvailableTextLength()) {
|
||||
m_scroll++;
|
||||
++m_scroll;
|
||||
x = bounds().x + border().left();
|
||||
for (c=m_scroll; utf8_begin != utf8_end; ++c) {
|
||||
int ch = (c < textlen ? *(utf8_begin+c) : ' ');
|
||||
|
||||
auto utf8_it = utf8_begin + MID(0, m_scroll, textlen);
|
||||
for (c=m_scroll; utf8_it != utf8_end; ++c, ++utf8_it) {
|
||||
int ch = (c < textlen ? *utf8_it: ' ');
|
||||
|
||||
x += font()->charWidth(ch);
|
||||
if (x > bounds().x2()-border().right()) {
|
||||
@ -353,7 +359,7 @@ bool Entry::onProcessMessage(Message* msg)
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_caret = c;
|
||||
m_caret = MID(0, c, textlen);
|
||||
move = false;
|
||||
is_dirty = true;
|
||||
invalidate();
|
||||
@ -450,8 +456,9 @@ void Entry::onSetText()
|
||||
{
|
||||
Widget::onSetText();
|
||||
|
||||
if (m_caret >= 0 && (std::size_t)m_caret > textLength())
|
||||
m_caret = (int)textLength();
|
||||
int textlen = textLength();
|
||||
if (m_caret >= 0 && m_caret > textlen)
|
||||
m_caret = textlen;
|
||||
}
|
||||
|
||||
void Entry::onChange()
|
||||
@ -482,11 +489,7 @@ int Entry::getCaretFromMouse(MouseMessage* mousemsg)
|
||||
|
||||
int x = bounds.x;
|
||||
|
||||
base::utf8_const_iterator utf8_it =
|
||||
(m_scroll < textlen ?
|
||||
utf8_begin + m_scroll:
|
||||
utf8_end);
|
||||
|
||||
auto utf8_it = utf8_begin + MID(0, m_scroll, textlen);
|
||||
int c = m_scroll;
|
||||
for (; utf8_it != utf8_end; ++c, ++utf8_it) {
|
||||
int w = font()->charWidth(*utf8_it);
|
||||
@ -505,7 +508,7 @@ int Entry::getCaretFromMouse(MouseMessage* mousemsg)
|
||||
}
|
||||
}
|
||||
|
||||
return caret;
|
||||
return MID(0, caret, textlen);
|
||||
}
|
||||
|
||||
void Entry::executeCmd(EntryCmd cmd, int unicodeChar, bool shift_pressed)
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "gfx/size.h"
|
||||
#include "she/display.h"
|
||||
#include "she/font.h"
|
||||
#include "she/scoped_surface_lock.h"
|
||||
#include "she/surface.h"
|
||||
#include "she/system.h"
|
||||
#include "ui/manager.h"
|
||||
@ -83,32 +82,32 @@ void Graphics::setDrawMode(DrawMode mode, int param)
|
||||
|
||||
gfx::Color Graphics::getPixel(int x, int y)
|
||||
{
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
return dst->getPixel(m_dx+x, m_dy+y);
|
||||
she::SurfaceLock lock(m_surface);
|
||||
return m_surface->getPixel(m_dx+x, m_dy+y);
|
||||
}
|
||||
|
||||
void Graphics::putPixel(gfx::Color color, int x, int y)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, 1, 1));
|
||||
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->putPixel(color, m_dx+x, m_dy+y);
|
||||
she::SurfaceLock lock(m_surface);
|
||||
m_surface->putPixel(color, m_dx+x, m_dy+y);
|
||||
}
|
||||
|
||||
void Graphics::drawHLine(gfx::Color color, int x, int y, int w)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, w, 1));
|
||||
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawHLine(color, m_dx+x, m_dy+y, w);
|
||||
she::SurfaceLock lock(m_surface);
|
||||
m_surface->drawHLine(color, m_dx+x, m_dy+y, w);
|
||||
}
|
||||
|
||||
void Graphics::drawVLine(gfx::Color color, int x, int y, int h)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, 1, h));
|
||||
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawVLine(color, m_dx+x, m_dy+y, h);
|
||||
she::SurfaceLock lock(m_surface);
|
||||
m_surface->drawVLine(color, m_dx+x, m_dy+y, h);
|
||||
}
|
||||
|
||||
void Graphics::drawLine(gfx::Color color, const gfx::Point& _a, const gfx::Point& _b)
|
||||
@ -117,8 +116,8 @@ void Graphics::drawLine(gfx::Color color, const gfx::Point& _a, const gfx::Point
|
||||
gfx::Point b(m_dx+_b.x, m_dy+_b.y);
|
||||
dirty(gfx::Rect(a, b));
|
||||
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawLine(color, a, b);
|
||||
she::SurfaceLock lock(m_surface);
|
||||
m_surface->drawLine(color, a, b);
|
||||
}
|
||||
|
||||
void Graphics::drawRect(gfx::Color color, const gfx::Rect& rcOrig)
|
||||
@ -127,8 +126,8 @@ void Graphics::drawRect(gfx::Color color, const gfx::Rect& rcOrig)
|
||||
rc.offset(m_dx, m_dy);
|
||||
dirty(rc);
|
||||
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawRect(color, rc);
|
||||
she::SurfaceLock lock(m_surface);
|
||||
m_surface->drawRect(color, rc);
|
||||
}
|
||||
|
||||
void Graphics::fillRect(gfx::Color color, const gfx::Rect& rcOrig)
|
||||
@ -137,8 +136,8 @@ void Graphics::fillRect(gfx::Color color, const gfx::Rect& rcOrig)
|
||||
rc.offset(m_dx, m_dy);
|
||||
dirty(rc);
|
||||
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->fillRect(color, rc);
|
||||
she::SurfaceLock lock(m_surface);
|
||||
m_surface->fillRect(color, rc);
|
||||
}
|
||||
|
||||
void Graphics::fillRegion(gfx::Color color, const gfx::Region& rgn)
|
||||
@ -163,27 +162,27 @@ void Graphics::drawSurface(she::Surface* surface, int x, int y)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, surface->width(), surface->height()));
|
||||
|
||||
she::ScopedSurfaceLock src(surface);
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawSurface(src, m_dx+x, m_dy+y);
|
||||
she::SurfaceLock lockSrc(surface);
|
||||
she::SurfaceLock lockDst(m_surface);
|
||||
m_surface->drawSurface(surface, m_dx+x, m_dy+y);
|
||||
}
|
||||
|
||||
void Graphics::drawRgbaSurface(she::Surface* surface, int x, int y)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, surface->width(), surface->height()));
|
||||
|
||||
she::ScopedSurfaceLock src(surface);
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawRgbaSurface(src, m_dx+x, m_dy+y);
|
||||
she::SurfaceLock lockSrc(surface);
|
||||
she::SurfaceLock lockDst(m_surface);
|
||||
m_surface->drawRgbaSurface(surface, m_dx+x, m_dy+y);
|
||||
}
|
||||
|
||||
void Graphics::drawColoredRgbaSurface(she::Surface* surface, gfx::Color color, int x, int y)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, surface->width(), surface->height()));
|
||||
|
||||
she::ScopedSurfaceLock src(surface);
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawColoredRgbaSurface(src, color, gfx::ColorNone,
|
||||
she::SurfaceLock lockSrc(surface);
|
||||
she::SurfaceLock lockDst(m_surface);
|
||||
m_surface->drawColoredRgbaSurface(surface, color, gfx::ColorNone,
|
||||
gfx::Clip(m_dx+x, m_dy+y, 0, 0, surface->width(), surface->height()));
|
||||
}
|
||||
|
||||
@ -191,9 +190,9 @@ void Graphics::blit(she::Surface* srcSurface, int srcx, int srcy, int dstx, int
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+dstx, m_dy+dsty, w, h));
|
||||
|
||||
she::ScopedSurfaceLock src(srcSurface);
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
src->blitTo(dst, srcx, srcy, m_dx+dstx, m_dy+dsty, w, h);
|
||||
she::SurfaceLock lockSrc(srcSurface);
|
||||
she::SurfaceLock lockDst(m_surface);
|
||||
srcSurface->blitTo(m_surface, srcx, srcy, m_dx+dstx, m_dy+dsty, w, h);
|
||||
}
|
||||
|
||||
void Graphics::setFont(she::Font* font)
|
||||
@ -205,8 +204,8 @@ void Graphics::drawChar(int chr, gfx::Color fg, gfx::Color bg, int x, int y)
|
||||
{
|
||||
dirty(gfx::Rect(gfx::Point(m_dx+x, m_dy+y), measureChar(chr)));
|
||||
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawChar(m_font, fg, bg, m_dx+x, m_dy+y, chr);
|
||||
she::SurfaceLock lock(m_surface);
|
||||
m_surface->drawChar(m_font, fg, bg, m_dx+x, m_dy+y, chr);
|
||||
}
|
||||
|
||||
void Graphics::drawString(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Point& ptOrig)
|
||||
@ -214,14 +213,14 @@ void Graphics::drawString(const std::string& str, gfx::Color fg, gfx::Color bg,
|
||||
gfx::Point pt(m_dx+ptOrig.x, m_dy+ptOrig.y);
|
||||
dirty(gfx::Rect(pt.x, pt.y, m_font->textLength(str), m_font->height()));
|
||||
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawString(m_font, fg, bg, pt.x, pt.y, str);
|
||||
she::SurfaceLock lock(m_surface);
|
||||
m_surface->drawString(m_font, fg, bg, pt.x, pt.y, str);
|
||||
}
|
||||
|
||||
void Graphics::drawUIString(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Point& pt,
|
||||
bool drawUnderscore)
|
||||
{
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
she::SurfaceLock lock(m_surface);
|
||||
base::utf8_const_iterator it(str.begin()), end(str.end());
|
||||
int x = m_dx+pt.x;
|
||||
int y = m_dy+pt.y;
|
||||
@ -236,14 +235,14 @@ void Graphics::drawUIString(const std::string& str, gfx::Color fg, gfx::Color bg
|
||||
underscored_w = m_font->charWidth(*it);
|
||||
}
|
||||
}
|
||||
dst->drawChar(m_font, fg, bg, x, y, *it);
|
||||
m_surface->drawChar(m_font, fg, bg, x, y, *it);
|
||||
x += m_font->charWidth(*it);
|
||||
++it;
|
||||
}
|
||||
|
||||
y += m_font->height();
|
||||
if (drawUnderscore && underscored_w > 0) {
|
||||
dst->fillRect(fg,
|
||||
m_surface->fillRect(fg,
|
||||
gfx::Rect(underscored_x, y, underscored_w, guiscale()));
|
||||
y += guiscale();
|
||||
}
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "she/display.h"
|
||||
#include "she/event.h"
|
||||
#include "she/event_queue.h"
|
||||
#include "she/scoped_surface_lock.h"
|
||||
#include "she/surface.h"
|
||||
#include "she/system.h"
|
||||
#include "ui/intern.h"
|
||||
@ -574,7 +573,7 @@ void Manager::enqueueMessage(Message* msg)
|
||||
#ifdef REPORT_EVENTS
|
||||
if (msg->type() == kKeyDownMessage ||
|
||||
msg->type() == kKeyUpMessage) {
|
||||
int mods = (int)static_cast<KeyMessage*>(msg)->keyModifiers();
|
||||
int mods = (int)static_cast<KeyMessage*>(msg)->modifiers();
|
||||
TRACE("Key%s scancode=%d unicode=%d mods=%s%s%s\n",
|
||||
(msg->type() == kKeyDownMessage ? "Down": "Up"),
|
||||
static_cast<KeyMessage*>(msg)->scancode(),
|
||||
@ -716,8 +715,8 @@ void Manager::setMouse(Widget* widget)
|
||||
std::cout << "Manager::setMouse ";
|
||||
if (widget) {
|
||||
std::cout << typeid(*widget).name();
|
||||
if (!widget->getId().empty())
|
||||
std::cout << " (" << widget->getId() << ")";
|
||||
if (!widget->id().empty())
|
||||
std::cout << " (" << widget->id() << ")";
|
||||
}
|
||||
else {
|
||||
std::cout << "null";
|
||||
@ -1258,8 +1257,8 @@ void Manager::pumpQueue()
|
||||
|
||||
std::cout << "Event " << msg->type() << " (" << string << ") "
|
||||
<< "for " << typeid(*widget).name();
|
||||
if (!widget->getId().empty())
|
||||
std::cout << " (" << widget->getId() << ")";
|
||||
if (!widget->id().empty())
|
||||
std::cout << " (" << widget->id() << ")";
|
||||
std::cout << std::endl;
|
||||
}
|
||||
#endif
|
||||
@ -1271,7 +1270,7 @@ void Manager::pumpQueue()
|
||||
continue;
|
||||
|
||||
PaintMessage* paintMsg = static_cast<PaintMessage*>(msg);
|
||||
she::NonDisposableSurface* surface = m_display->getSurface();
|
||||
she::Surface* surface = m_display->getSurface();
|
||||
gfx::Rect oldClip = surface->getClipBounds();
|
||||
|
||||
if (surface->intersectClipRect(paintMsg->rect())) {
|
||||
@ -1286,8 +1285,8 @@ void Manager::pumpQueue()
|
||||
|
||||
#ifdef DEBUG_PAINT_EVENTS
|
||||
{
|
||||
she::ScopedSurfaceLock lock(surface);
|
||||
lock->fillRect(gfx::rgba(0, 0, 255), paintMsg->rect());
|
||||
she::SurfaceLock lock(surface);
|
||||
surface->fillRect(gfx::rgba(0, 0, 255), paintMsg->rect());
|
||||
}
|
||||
|
||||
if (m_display)
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -11,8 +11,6 @@
|
||||
#include "ui/manager.h"
|
||||
|
||||
#include "she/display.h"
|
||||
#include "she/locked_surface.h"
|
||||
#include "she/scoped_surface_lock.h"
|
||||
#include "she/surface.h"
|
||||
#include "she/system.h"
|
||||
|
||||
@ -30,13 +28,14 @@ void move_region(Manager* manager, const Region& region, int dx, int dy)
|
||||
if (!display)
|
||||
return;
|
||||
|
||||
she::ScopedSurfaceLock lock(display->getSurface());
|
||||
she::Surface* surface = display->getSurface();
|
||||
she::SurfaceLock lock(surface);
|
||||
std::size_t nrects = region.size();
|
||||
|
||||
// Blit directly screen to screen.
|
||||
if (nrects == 1) {
|
||||
gfx::Rect rc = region[0];
|
||||
lock->scrollTo(rc, dx, dy);
|
||||
surface->scrollTo(rc, dx, dy);
|
||||
|
||||
rc.offset(dx, dy);
|
||||
Manager::getDefault()->dirtyRect(rc);
|
||||
@ -45,28 +44,27 @@ void move_region(Manager* manager, const Region& region, int dx, int dy)
|
||||
else if (nrects > 1) {
|
||||
std::vector<she::Surface*> images(nrects);
|
||||
Region::const_iterator it, begin=region.begin(), end=region.end();
|
||||
she::Surface* sur;
|
||||
int c;
|
||||
|
||||
for (c=0, it=begin; it != end; ++it, ++c) {
|
||||
const Rect& rc = *it;
|
||||
sur = system->createSurface(rc.w, rc.h);
|
||||
she::Surface* tmpSur = system->createSurface(rc.w, rc.h);
|
||||
{
|
||||
she::ScopedSurfaceLock surlock(sur);
|
||||
lock->blitTo(surlock, rc.x, rc.y, 0, 0, rc.w, rc.h);
|
||||
she::SurfaceLock tmpSurLock(tmpSur);
|
||||
surface->blitTo(tmpSur, rc.x, rc.y, 0, 0, rc.w, rc.h);
|
||||
}
|
||||
images[c] = sur;
|
||||
images[c] = tmpSur;
|
||||
}
|
||||
|
||||
for (c=0, it=begin; it != end; ++it, ++c) {
|
||||
gfx::Rect rc((*it).x+dx, (*it).y+dy, (*it).w, (*it).h);
|
||||
sur = images[c];
|
||||
she::Surface* tmpSur = images[c];
|
||||
{
|
||||
she::ScopedSurfaceLock surlock(sur);
|
||||
surlock->blitTo(lock, 0, 0, rc.x, rc.y, rc.w, rc.h);
|
||||
she::SurfaceLock tmpSurLock(tmpSur);
|
||||
tmpSur->blitTo(surface, 0, 0, rc.x, rc.y, rc.w, rc.h);
|
||||
manager->dirtyRect(rc);
|
||||
}
|
||||
sur->dispose();
|
||||
tmpSur->dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2001-2013, 2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -10,8 +10,7 @@
|
||||
|
||||
#include "ui/overlay.h"
|
||||
|
||||
#include "she/locked_surface.h"
|
||||
#include "she/scoped_surface_lock.h"
|
||||
#include "she/surface.h"
|
||||
#include "she/system.h"
|
||||
#include "ui/manager.h"
|
||||
|
||||
@ -55,13 +54,13 @@ gfx::Rect Overlay::bounds() const
|
||||
return gfx::Rect(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void Overlay::drawOverlay(she::LockedSurface* screen)
|
||||
void Overlay::drawOverlay(she::Surface* screen)
|
||||
{
|
||||
if (!m_surface)
|
||||
return;
|
||||
|
||||
she::ScopedSurfaceLock lockedSurface(m_surface);
|
||||
screen->drawRgbaSurface(lockedSurface, m_pos.x, m_pos.y);
|
||||
she::SurfaceLock lock(m_surface);
|
||||
screen->drawRgbaSurface(m_surface, m_pos.x, m_pos.y);
|
||||
|
||||
Manager::getDefault()->dirtyRect(
|
||||
gfx::Rect(m_pos.x, m_pos.y,
|
||||
@ -74,7 +73,7 @@ void Overlay::moveOverlay(const gfx::Point& newPos)
|
||||
m_pos = newPos;
|
||||
}
|
||||
|
||||
void Overlay::captureOverlappedArea(she::LockedSurface* screen)
|
||||
void Overlay::captureOverlappedArea(she::Surface* screen)
|
||||
{
|
||||
if (!m_surface)
|
||||
return;
|
||||
@ -82,12 +81,12 @@ void Overlay::captureOverlappedArea(she::LockedSurface* screen)
|
||||
if (!m_overlap)
|
||||
m_overlap = she::instance()->createSurface(m_surface->width(), m_surface->height());
|
||||
|
||||
she::ScopedSurfaceLock lock(m_overlap);
|
||||
screen->blitTo(lock, m_pos.x, m_pos.y, 0, 0,
|
||||
she::SurfaceLock lock(m_overlap);
|
||||
screen->blitTo(m_overlap, m_pos.x, m_pos.y, 0, 0,
|
||||
m_overlap->width(), m_overlap->height());
|
||||
}
|
||||
|
||||
void Overlay::restoreOverlappedArea(she::LockedSurface* screen)
|
||||
void Overlay::restoreOverlappedArea(she::Surface* screen)
|
||||
{
|
||||
if (!m_surface)
|
||||
return;
|
||||
@ -95,9 +94,9 @@ void Overlay::restoreOverlappedArea(she::LockedSurface* screen)
|
||||
if (!m_overlap)
|
||||
return;
|
||||
|
||||
she::ScopedSurfaceLock lock(m_overlap);
|
||||
lock->blitTo(screen, 0, 0, m_pos.x, m_pos.y,
|
||||
m_overlap->width(), m_overlap->height());
|
||||
she::SurfaceLock lock(m_overlap);
|
||||
m_overlap->blitTo(screen, 0, 0, m_pos.x, m_pos.y,
|
||||
m_overlap->width(), m_overlap->height());
|
||||
|
||||
Manager::getDefault()->dirtyRect(
|
||||
gfx::Rect(m_pos.x, m_pos.y,
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2001-2013, 2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -14,7 +14,6 @@
|
||||
|
||||
namespace she {
|
||||
class Surface;
|
||||
class LockedSurface;
|
||||
}
|
||||
|
||||
namespace ui {
|
||||
@ -34,10 +33,10 @@ namespace ui {
|
||||
const gfx::Point& position() const { return m_pos; }
|
||||
gfx::Rect bounds() const;
|
||||
|
||||
void captureOverlappedArea(she::LockedSurface* screen);
|
||||
void restoreOverlappedArea(she::LockedSurface* screen);
|
||||
void captureOverlappedArea(she::Surface* screen);
|
||||
void restoreOverlappedArea(she::Surface* screen);
|
||||
|
||||
void drawOverlay(she::LockedSurface* screen);
|
||||
void drawOverlay(she::Surface* screen);
|
||||
void moveOverlay(const gfx::Point& newPos);
|
||||
|
||||
bool operator<(const Overlay& other) const {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2001-2013, 2015 David Capello
|
||||
// Copyright (C) 2001-2013, 2015, 2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -11,7 +11,7 @@
|
||||
#include "ui/overlay_manager.h"
|
||||
|
||||
#include "she/display.h"
|
||||
#include "she/scoped_surface_lock.h"
|
||||
#include "she/surface.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/overlay.h"
|
||||
|
||||
@ -66,9 +66,9 @@ void OverlayManager::captureOverlappedAreas()
|
||||
return;
|
||||
|
||||
she::Surface* displaySurface = manager->getDisplay()->getSurface();
|
||||
she::ScopedSurfaceLock lockedDisplaySurface(displaySurface);
|
||||
she::SurfaceLock lock(displaySurface);
|
||||
for (Overlay* overlay : *this)
|
||||
overlay->captureOverlappedArea(lockedDisplaySurface);
|
||||
overlay->captureOverlappedArea(displaySurface);
|
||||
}
|
||||
|
||||
void OverlayManager::restoreOverlappedAreas()
|
||||
@ -78,9 +78,9 @@ void OverlayManager::restoreOverlappedAreas()
|
||||
return;
|
||||
|
||||
she::Surface* displaySurface = manager->getDisplay()->getSurface();
|
||||
she::ScopedSurfaceLock lockedDisplaySurface(displaySurface);
|
||||
she::SurfaceLock lock(displaySurface);
|
||||
for (Overlay* overlay : *this)
|
||||
overlay->restoreOverlappedArea(lockedDisplaySurface);
|
||||
overlay->restoreOverlappedArea(displaySurface);
|
||||
}
|
||||
|
||||
void OverlayManager::drawOverlays()
|
||||
@ -90,9 +90,9 @@ void OverlayManager::drawOverlays()
|
||||
return;
|
||||
|
||||
she::Surface* displaySurface = manager->getDisplay()->getSurface();
|
||||
she::ScopedSurfaceLock lockedDisplaySurface(displaySurface);
|
||||
she::SurfaceLock lock(displaySurface);
|
||||
for (Overlay* overlay : *this)
|
||||
overlay->drawOverlay(lockedDisplaySurface);
|
||||
overlay->drawOverlay(displaySurface);
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
|
@ -27,7 +27,7 @@
|
||||
#ifdef DEBUG_SCROLL_EVENTS
|
||||
#include "base/thread.h"
|
||||
#include "she/display.h"
|
||||
#include "she/scoped_surface_lock.h"
|
||||
#include "she/surface.h"
|
||||
#endif
|
||||
|
||||
#include <queue>
|
||||
@ -326,9 +326,10 @@ void View::onSetViewScroll(const gfx::Point& pt)
|
||||
display->flip(gfx::Rect(0, 0, display_w(), display_h()));
|
||||
base::this_thread::sleep_for(0.002);
|
||||
{
|
||||
she::ScopedSurfaceLock lock(display->getSurface());
|
||||
she::Surface* surface = display->getSurface();
|
||||
she::SurfaceLock lock(surface);
|
||||
for (const auto& rc : invalidRegion)
|
||||
lock->fillRect(gfx::rgba(255, 0, 0), rc);
|
||||
surface->fillRect(gfx::rgba(255, 0, 0), rc);
|
||||
}
|
||||
if (display)
|
||||
display->flip(gfx::Rect(0, 0, display_w(), display_h()));
|
||||
|
@ -4,7 +4,7 @@
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
/* #define REPORT_SIGNALS */
|
||||
// #define REPORT_SIGNALS
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
@ -13,9 +13,9 @@
|
||||
#include "ui/widget.h"
|
||||
|
||||
#include "base/memory.h"
|
||||
#include "base/string.h"
|
||||
#include "she/display.h"
|
||||
#include "she/font.h"
|
||||
#include "she/scoped_surface_lock.h"
|
||||
#include "she/surface.h"
|
||||
#include "she/system.h"
|
||||
#include "ui/init_theme_event.h"
|
||||
@ -125,6 +125,11 @@ double Widget::textDouble() const
|
||||
return strtod(m_text.c_str(), NULL);
|
||||
}
|
||||
|
||||
int Widget::textLength() const
|
||||
{
|
||||
return base::utf8_length(text());
|
||||
}
|
||||
|
||||
void Widget::setText(const std::string& text)
|
||||
{
|
||||
setTextQuiet(text);
|
||||
@ -1055,9 +1060,11 @@ public:
|
||||
|
||||
void operator()(Graphics* graphics) {
|
||||
{
|
||||
she::ScopedSurfaceLock src(m_surface);
|
||||
she::ScopedSurfaceLock dst(she::instance()->defaultDisplay()->getSurface());
|
||||
src->blitTo(dst, 0, 0, m_pt.x, m_pt.y,
|
||||
she::Surface* dst = she::instance()->defaultDisplay()->getSurface();
|
||||
she::SurfaceLock lockSrc(m_surface);
|
||||
she::SurfaceLock lockDst(dst);
|
||||
m_surface->blitTo(
|
||||
dst, 0, 0, m_pt.x, m_pt.y,
|
||||
m_surface->width(), m_surface->height());
|
||||
}
|
||||
m_surface->dispose();
|
||||
|
@ -82,7 +82,7 @@ namespace ui {
|
||||
const std::string& text() const { return m_text; }
|
||||
int textInt() const;
|
||||
double textDouble() const;
|
||||
std::size_t textLength() const { return m_text.size(); }
|
||||
int textLength() const;
|
||||
void setText(const std::string& text);
|
||||
void setTextf(const char* text, ...);
|
||||
void setTextQuiet(const std::string& text);
|
||||
|
50
third_party/pixman-cmake/pixman-version.h.cmake
vendored
50
third_party/pixman-cmake/pixman-version.h.cmake
vendored
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2008 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#ifndef PIXMAN_VERSION_H__
|
||||
#define PIXMAN_VERSION_H__
|
||||
|
||||
#ifndef PIXMAN_H__
|
||||
# error pixman-version.h should only be included by pixman.h
|
||||
#endif
|
||||
|
||||
#define PIXMAN_VERSION_MAJOR @PIXMAN_VERSION_MAJOR@
|
||||
#define PIXMAN_VERSION_MINOR @PIXMAN_VERSION_MINOR@
|
||||
#define PIXMAN_VERSION_MICRO @PIXMAN_VERSION_MICRO@
|
||||
|
||||
#define PIXMAN_VERSION_STRING "@PIXMAN_VERSION_MAJOR@.@PIXMAN_VERSION_MINOR@.@PIXMAN_VERSION_MICRO@"
|
||||
|
||||
#define PIXMAN_VERSION_ENCODE(major, minor, micro) ( \
|
||||
((major) * 10000) \
|
||||
+ ((minor) * 100) \
|
||||
+ ((micro) * 1))
|
||||
|
||||
#define PIXMAN_VERSION PIXMAN_VERSION_ENCODE( \
|
||||
PIXMAN_VERSION_MAJOR, \
|
||||
PIXMAN_VERSION_MINOR, \
|
||||
PIXMAN_VERSION_MICRO)
|
||||
|
||||
#endif /* PIXMAN_VERSION_H__ */
|
Loading…
x
Reference in New Issue
Block a user