/*
This file is part of Magnum .
Copyright © 2010 , 2011 , 2012 , 2013 , 2014 , 2015 , 2016 , 2017 , 2018 , 2019 ,
2020 , 2021 , 2022 , 2023 Vladimír Vondruš < mosra @ centrum . cz >
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 .
*/
# include "AbstractGlyphCache.h"
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
# include <Corrade/Containers/Array.h>
# include <Corrade/Containers/GrowableArray.h>
# include <Corrade/Containers/EnumSet.hpp>
# include <Corrade/Containers/Optional.h>
# include <Corrade/Containers/Triple.h>
# include <Corrade/Containers/StridedArrayView.h>
# include "Magnum/Image.h"
# include "Magnum/ImageView.h"
# include "Magnum/PixelFormat.h"
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
# include "Magnum/Math/Range.h"
# include "Magnum/TextureTools/Atlas.h"
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
# ifdef MAGNUM_BUILD_DEPRECATED
# include <Corrade/Containers/ArrayViewStl.h>
# include <Corrade/Utility/Algorithms.h>
# endif
namespace Magnum { namespace Text {
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
Debug & operator < < ( Debug & debug , const GlyphCacheFeature value ) {
debug < < " Text::GlyphCacheFeature " < < Debug : : nospace ;
switch ( value ) {
/* LCOV_EXCL_START */
# define _c(v) case GlyphCacheFeature::v: return debug << "::" #v;
_c ( ImageProcessing )
_c ( ProcessedImageDownload )
# undef _c
/* LCOV_EXCL_STOP */
}
return debug < < " ( " < < Debug : : nospace < < reinterpret_cast < void * > ( UnsignedByte ( value ) ) < < Debug : : nospace < < " ) " ;
}
Debug & operator < < ( Debug & debug , const GlyphCacheFeatures value ) {
return Containers : : enumSetDebugOutput ( debug , value , " Text::GlyphCacheFeatures{} " , {
/* ProcessedImageDownload is a superset of ImageProcessing, has to be
first */
GlyphCacheFeature : : ProcessedImageDownload ,
GlyphCacheFeature : : ImageProcessing
} ) ;
}
struct AbstractGlyphCache : : State {
explicit State ( PixelFormat format , const Vector3i & size , const Vector2i & padding ) : image { format , size , Containers : : Array < char > { ValueInit , 4 * ( ( pixelFormatSize ( format ) * size . x ( ) + 3 ) / 4 ) * size . y ( ) * size . z ( ) } } , atlas { size } , padding { padding } {
/* Flags are currently cleared as well, will be enabled back in a later
step once the behavior is specified ( with negative ranges ) and
Math : : join ( ) is fixed to handle those correctly . */
atlas . setPadding ( padding )
. clearFlags ( TextureTools : : AtlasLandfillFlag : : RotatePortrait |
TextureTools : : AtlasLandfillFlag : : RotateLandscape ) ;
}
Image3D image ;
TextureTools : : AtlasLandfill atlas ;
Vector2i padding ;
/* First element is glyph position relative to a point on the baseline,
second layer in the texture atlas , third a region in the atlas
slice . Index of the item is ID of the glyph in the cache , refered to
from the fontGlyphMapping array . Index 0 is reserved for an invalid
glyph . */
Containers : : Array < Containers : : Triple < Vector2i , Int , Range2Di > > glyphs ;
/* `fontRanges[i]` to `fontRanges[i + 1]` is the range in
` fontGlyphMapping ` containing a mapping for glyphs from font ` i ` ,
` fontGlyphMapping [ fontRanges [ i ] ] + j ` is then mapping from glyph ID ` j `
from font ` i ` to index in the ` glyphs ` array , or is 0 if given
glyph isn ' t present in the cache ( which then maps to the invalid
glyph ) . */
struct Font {
UnsignedInt offset ;
/* 4 bytes free on 64b, but not so critical I think */
const AbstractFont * pointer ;
} ;
Containers : : Array < Font > fonts ;
/* With an assumption that majority of font glyphs get put into a cache,
this achieves O ( 1 ) mapping from a font ID + font - specific glyph ID pair
to a cache - global glyph ID with far less overhead than a hashmap would ,
and much less memory used as well compared to storing a key , value and a
hash for each mapping entry .
Another assumption is that there ' s no more than 64 k glyphs in total ,
which makes the mapping save half memory compared to storing 32 - bit
ints . 64 K glyphs is enough to fill a 4 K texture with 16 x16 glyphs , which
seems enough for now . It however might get reached at some point in
practice , in which case the type would simply get changed to a 32 - bit
one ( and the assertion in addGlyph ( ) then removed ) . */
Containers : : Array < UnsignedShort > fontGlyphMapping ;
} ;
AbstractGlyphCache : : AbstractGlyphCache ( const PixelFormat format , const Vector3i & size , const Vector2i & padding ) {
CORRADE_ASSERT ( size . product ( ) ,
" Text::AbstractGlyphCache: expected non-zero size, got " < < Debug : : packed < < size , ) ;
/* Creating the state only after the assert as the AtlasLandfill would
assert on zero size as well */
_state . emplace ( format , size , padding ) ;
/* Default invalid glyph -- empty / zero-area */
arrayAppend ( _state - > glyphs , InPlaceInit ) ;
/* There are no fonts yet */
arrayAppend ( _state - > fonts , InPlaceInit , 0u , nullptr ) ;
}
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
AbstractGlyphCache : : AbstractGlyphCache ( const PixelFormat format , const Vector3i & size ) : AbstractGlyphCache { format , size , { } } { }
AbstractGlyphCache : : AbstractGlyphCache ( const PixelFormat format , const Vector2i & size , const Vector2i & padding ) : AbstractGlyphCache { format , Vector3i { size , 1 } , padding } { }
AbstractGlyphCache : : AbstractGlyphCache ( const PixelFormat format , const Vector2i & size ) : AbstractGlyphCache { format , size , { } } { }
# ifdef MAGNUM_BUILD_DEPRECATED
AbstractGlyphCache : : AbstractGlyphCache ( const Vector2i & size , const Vector2i & padding ) : AbstractGlyphCache { PixelFormat : : R8Unorm , size , padding } { }
AbstractGlyphCache : : AbstractGlyphCache ( const Vector2i & size ) : AbstractGlyphCache { PixelFormat : : R8Unorm , size , { } } { }
# endif
AbstractGlyphCache : : AbstractGlyphCache ( AbstractGlyphCache & & ) noexcept = default ;
AbstractGlyphCache : : ~ AbstractGlyphCache ( ) = default ;
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
AbstractGlyphCache & AbstractGlyphCache : : operator = ( AbstractGlyphCache & & ) noexcept = default ;
PixelFormat AbstractGlyphCache : : format ( ) const {
return _state - > image . format ( ) ;
}
Vector3i AbstractGlyphCache : : size ( ) const {
return _state - > image . size ( ) ;
}
# ifdef MAGNUM_BUILD_DEPRECATED
Vector2i AbstractGlyphCache : : textureSize ( ) const {
CORRADE_ASSERT ( _state - > image . size ( ) . z ( ) = = 1 ,
" Text::AbstractGlyphCache::textureSize(): can't be used on an array glyph cache " , { } ) ;
return _state - > image . size ( ) . xy ( ) ;
}
# endif
Vector2i AbstractGlyphCache : : padding ( ) const {
return _state - > padding ;
}
UnsignedInt AbstractGlyphCache : : fontCount ( ) const {
return _state - > fonts . size ( ) - 1 ;
}
UnsignedInt AbstractGlyphCache : : glyphCount ( ) const {
return _state - > glyphs . size ( ) ;
}
TextureTools : : AtlasLandfill & AbstractGlyphCache : : atlas ( ) {
return _state - > atlas ;
}
const TextureTools : : AtlasLandfill & AbstractGlyphCache : : atlas ( ) const {
return _state - > atlas ;
}
void AbstractGlyphCache : : setInvalidGlyph ( const Vector2i & offset , const Int layer , const Range2Di & rectangle ) {
State & state = * _state ;
/** @todo expand once rotations (and thus negative rectangle sizes) are
supported */
const Range2Di rectanglePadded = rectangle . padded ( state . padding ) ;
# ifndef CORRADE_NO_ASSERT
const Range2Dui rectangleu { rectangle } ;
const Range2Dui rectanglePaddedu { rectanglePadded } ;
# endif
CORRADE_ASSERT ( UnsignedInt ( layer ) < UnsignedInt ( state . image . size ( ) . z ( ) ) & & ( rectangleu . min ( ) < = rectangleu . max ( ) ) . all ( ) & & ( rectanglePaddedu . min ( ) < = Vector2ui { state . image . size ( ) . xy ( ) } ) . all ( ) & & ( rectanglePaddedu . max ( ) < = Vector2ui { state . image . size ( ) . xy ( ) } ) . all ( ) ,
" Text::AbstractGlyphCache::setInvalidGlyph(): layer " < < layer < < " and rectangle " < < Debug : : packed < < rectangle < < " out of range for size " < < Debug : : packed < < state . image . size ( ) < < " and padding " < < Debug : : packed < < state . padding , ) ;
state . glyphs [ 0 ] = { offset - _state - > padding , layer , rectanglePadded } ;
}
void AbstractGlyphCache : : setInvalidGlyph ( const Vector2i & offset , const Range2Di & rectangle ) {
CORRADE_ASSERT ( _state - > image . size ( ) . z ( ) = = 1 ,
" Text::AbstractGlyphCache::setInvalidGlyph(): use the layer overload for an array glyph cache " , ) ;
setInvalidGlyph ( offset , 0 , rectangle ) ;
}
UnsignedInt AbstractGlyphCache : : addFont ( const UnsignedInt glyphCount , const AbstractFont * const pointer ) {
State & state = * _state ;
# ifndef CORRADE_NO_ASSERT
for ( UnsignedInt i = 0 ; i ! = state . fonts . size ( ) - 1 ; + + i )
CORRADE_ASSERT ( ! pointer | | state . fonts [ i ] . pointer ! = pointer ,
" Text::AbstractGlyphCache::addFont(): pointer " < < pointer < < " already used for font " < < i , { } ) ;
# endif
/* The last item in the font array now becomes the new font (and its offset
should be the size of the fontGlyphMapping array ) , assign the pointer to
it . Add a new item after which is the end offset sentinel . */
CORRADE_INTERNAL_ASSERT ( state . fontGlyphMapping . size ( ) = = state . fonts . back ( ) . offset ) ;
state . fonts . back ( ) . pointer = pointer ;
arrayAppend ( state . fonts , InPlaceInit ,
state . fonts . back ( ) . offset + glyphCount ,
nullptr ) ;
/** @todo er, some arrayAppend with ValueInit + count? there's already
arrayResize ( ) with the same signature */
for ( UnsignedShort & i : arrayAppend ( state . fontGlyphMapping , NoInit , glyphCount ) )
i = 0 ;
return state . fonts . size ( ) - 2 ;
}
UnsignedInt AbstractGlyphCache : : fontGlyphCount ( const UnsignedInt fontId ) const {
const State & state = * _state ;
CORRADE_ASSERT ( fontId < state . fonts . size ( ) - 1 ,
" Text::AbstractGlyphCache::fontGlyphCount(): index " < < fontId < < " out of range for " < < state . fonts . size ( ) - 1 < < " fonts " , { } ) ;
return state . fonts [ fontId + 1 ] . offset - state . fonts [ fontId ] . offset ;
}
const AbstractFont * AbstractGlyphCache : : fontPointer ( const UnsignedInt fontId ) const {
const State & state = * _state ;
CORRADE_ASSERT ( fontId < state . fonts . size ( ) - 1 ,
" Text::AbstractGlyphCache::fontPointer(): index " < < fontId < < " out of range for " < < state . fonts . size ( ) - 1 < < " fonts " , { } ) ;
return state . fonts [ fontId ] . pointer ;
}
Containers : : Optional < UnsignedInt > AbstractGlyphCache : : findFont ( const AbstractFont & font ) const {
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
const State & state = * _state ;
for ( UnsignedInt i = 0 ; i ! = state . fonts . size ( ) - 1 ; + + i )
if ( state . fonts [ i ] . pointer = = & font ) return i ;
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
return { } ;
}
# ifdef MAGNUM_BUILD_DEPRECATED
std : : vector < Range2Di > AbstractGlyphCache : : reserve ( const std : : vector < Vector2i > & sizes ) {
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
State & state = * _state ;
CORRADE_ASSERT ( state . image . size ( ) . z ( ) = = 1 ,
" Text::AbstractGlyphCache::reserve(): can't be used on an array glyph cache " , { } ) ;
/* This is technically possible now, but we just don't bother for the
compatibility API as it would need to be additionally tested */
CORRADE_ASSERT ( state . fonts . size ( ) = = 1 ,
" Text::AbstractGlyphCache::reserve(): reserving space in non-empty cache is not yet implemented " , { } ) ;
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
/* Append an empty font range just to prevent reserve() from being called
again */
arrayAppend ( state . fonts , InPlaceInit , 0u , nullptr ) ;
/* Disable rotations in the atlas as the old API doesn't expect them */
const TextureTools : : AtlasLandfillFlags previousFlags = state . atlas . flags ( ) ;
state . atlas . clearFlags ( TextureTools : : AtlasLandfillFlag : : RotatePortrait |
TextureTools : : AtlasLandfillFlag : : RotateLandscape ) ;
/* Create the output array */
std : : vector < Range2Di > out ( sizes . size ( ) ) ;
for ( std : : size_t i = 0 ; i ! = sizes . size ( ) ; + + i )
out [ i ] . max ( ) = sizes [ i ] ;
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
const bool succeeded = state . atlas . add (
Containers : : stridedArrayView ( out ) . slice ( & Range2Di : : max ) ,
Containers : : stridedArrayView ( out ) . slice ( & Range2Di : : min ) ) ;
/* Restore previous flags back */
state . atlas . setFlags ( previousFlags ) ;
/* The error message matches what the old TextureTools::atlas() did. Not
great , but that ' s the interface we should stay compatible with . */
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
if ( ! succeeded ) {
Error { } < < " Text::AbstractGlyphCache::reserve(): requested atlas size "
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
< < state . image . size ( ) . xy ( ) < < " is too small to fit "
< < sizes . size ( ) < < " textures. Generated atlas will be empty. " ;
return { } ;
}
/* Update the ranges max values to match the new offsets */
for ( std : : size_t i = 0 ; i ! = sizes . size ( ) ; + + i )
out [ i ] . max ( ) + = out [ i ] . min ( ) ;
return out ;
}
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
# endif
UnsignedInt AbstractGlyphCache : : addGlyph ( const UnsignedInt fontId , const UnsignedInt fontGlyphId , const Vector2i & offset , const Int layer , const Range2Di & rectangle ) {
State & state = * _state ;
CORRADE_ASSERT ( fontId < state . fonts . size ( ) - 1 ,
" Text::AbstractGlyphCache::addGlyph(): index " < < fontId < < " out of range for " < < state . fonts . size ( ) - 1 < < " fonts " , { } ) ;
const UnsignedInt fontOffset = state . fonts [ fontId ] . offset ;
CORRADE_ASSERT ( fontGlyphId < state . fonts [ fontId + 1 ] . offset - fontOffset ,
" Text::AbstractGlyphCache::addGlyph(): index " < < fontGlyphId < < " out of range for " < < state . fonts [ fontId + 1 ] . offset - fontOffset < < " glyphs in font " < < fontId , { } ) ;
CORRADE_ASSERT ( ! state . fontGlyphMapping [ fontOffset + fontGlyphId ] ,
" Text::AbstractGlyphCache::addGlyph(): glyph " < < fontGlyphId < < " in font " < < fontId < < " already added at index " < < state . fontGlyphMapping [ fontOffset + fontGlyphId ] , { } ) ;
/** @todo expand once rotations (and thus negative rectangle sizes) are
supported */
const Range2Di rectanglePadded = rectangle . padded ( state . padding ) ;
# ifndef CORRADE_NO_ASSERT
const Range2Dui rectangleu { rectangle } ;
const Range2Dui rectanglePaddedu { rectanglePadded } ;
# endif
CORRADE_ASSERT ( UnsignedInt ( layer ) < UnsignedInt ( state . image . size ( ) . z ( ) ) & & ( rectangleu . min ( ) < = rectangleu . max ( ) ) . all ( ) & & ( rectanglePaddedu . min ( ) < = Vector2ui { state . image . size ( ) . xy ( ) } ) . all ( ) & & ( rectanglePaddedu . max ( ) < = Vector2ui { state . image . size ( ) . xy ( ) } ) . all ( ) ,
" Text::AbstractGlyphCache::addGlyph(): layer " < < layer < < " and rectangle " < < Debug : : packed < < rectangle < < " out of range for size " < < Debug : : packed < < state . image . size ( ) < < " and padding " < < Debug : : packed < < state . padding , { } ) ;
const UnsignedInt glyphId = state . glyphs . size ( ) ;
/* The fontGlyphMapping entries are 16-bit to save memory, can't have IDs
beyond that . See its documentation for more reasoning . */
CORRADE_ASSERT ( glyphId < 65536 ,
" Text::AbstractGlyphCache::addGlyph(): only at most 65536 glyphs can be added " , { } ) ;
state . fontGlyphMapping [ fontOffset + fontGlyphId ] = glyphId ;
arrayAppend ( state . glyphs , InPlaceInit , offset - _state - > padding , layer , rectangle . padded ( _state - > padding ) ) ;
return glyphId ;
}
UnsignedInt AbstractGlyphCache : : addGlyph ( const UnsignedInt fontId , const UnsignedInt fontGlyphId , const Vector2i & offset , const Range2Di & rectangle ) {
CORRADE_ASSERT ( _state - > image . size ( ) . z ( ) = = 1 ,
" Text::AbstractGlyphCache::addGlyph(): use the layer overload for an array glyph cache " , { } ) ;
return addGlyph ( fontId , fontGlyphId , offset , 0 , rectangle ) ;
}
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
# ifdef MAGNUM_BUILD_DEPRECATED
void AbstractGlyphCache : : insert ( const UnsignedInt glyph , const Vector2i & offset , const Range2Di & rectangle ) {
State & state = * _state ;
CORRADE_ASSERT ( state . image . size ( ) . z ( ) = = 1 ,
" Text::AbstractGlyphCache::insert(): can't be used on an array glyph cache " , ) ;
CORRADE_ASSERT ( state . fonts . size ( ) < = 2 ,
" Text::AbstractGlyphCache::insert(): can't be used on a multi-font glyph cache " , ) ;
/* Overwriting "Not Found" glyph */
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
if ( glyph = = 0 ) {
setInvalidGlyph ( offset , rectangle ) ;
/* Inserting new glyph. Add the first ever font and ajust the font range if
needed . */
} else {
if ( state . fonts . size ( ) = = 1 )
arrayAppend ( _state - > fonts , InPlaceInit , 0u , nullptr ) ;
if ( glyph > = state . fonts [ 1 ] . offset ) {
arrayResize ( state . fontGlyphMapping , glyph + 1 ) ;
state . fonts [ 1 ] . offset = glyph + 1 ;
}
addGlyph ( 0 , glyph , offset , rectangle ) ;
}
}
# endif
MutableImageView3D AbstractGlyphCache : : image ( ) {
return _state - > image ;
}
ImageView3D AbstractGlyphCache : : image ( ) const {
return _state - > image ;
}
void AbstractGlyphCache : : flushImage ( const Range3Di & range ) {
State & state = * _state ;
# ifndef CORRADE_NO_ASSERT
const Range3Dui rangeu { range } ;
# endif
CORRADE_ASSERT ( ( rangeu . min ( ) < = rangeu . max ( ) ) . all ( ) & & ( rangeu . max ( ) < = Vector3ui { state . image . size ( ) } ) . all ( ) ,
" Text::AbstractGlyphCache::flushImage(): " < < Debug : : packed < < range < < " out of range for size " < < Debug : : packed < < state . image . size ( ) , ) ;
/** @todo ugh have slicing on images directly already */
PixelStorage storage ;
storage . setRowLength ( state . image . size ( ) . x ( ) )
. setSkip ( range . min ( ) ) ;
/* Set image height only if it's an array glyph cache, as otherwise it'd
cause errors on ES2 that doesn ' t support this pixel storage state */
if ( state . image . size ( ) . z ( ) ! = 1 )
storage . setImageHeight ( state . image . size ( ) . y ( ) ) ;
doSetImage ( range . min ( ) , ImageView3D {
storage ,
state . image . format ( ) ,
range . size ( ) ,
state . image . data ( ) } ) ;
}
void AbstractGlyphCache : : flushImage ( Int layer , const Range2Di & range ) {
flushImage ( { { range . min ( ) , layer } ,
{ range . max ( ) , layer + 1 } } ) ;
}
void AbstractGlyphCache : : flushImage ( const Range2Di & range ) {
CORRADE_ASSERT ( _state - > image . size ( ) . z ( ) = = 1 ,
" Text::AbstractGlyphCache::flushImage(): use the 3D or layer overload for an array glyph cache " , ) ;
flushImage ( 0 , range ) ;
}
void AbstractGlyphCache : : doSetImage ( const Vector3i & offset , const ImageView3D & image ) {
if ( _state - > image . size ( ) . z ( ) = = 1 )
/** @todo ugh have slicing on images directly already */
return doSetImage ( offset . xy ( ) , ImageView2D { image . storage ( ) , image . format ( ) , image . size ( ) . xy ( ) , image . data ( ) } ) ;
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
CORRADE_ASSERT_UNREACHABLE ( " Text::AbstractGlyphCache::image(): not implemented by derived class " , ) ;
}
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
void AbstractGlyphCache : : doSetImage ( const Vector2i & , const ImageView2D & ) {
CORRADE_ASSERT_UNREACHABLE ( " Text::AbstractGlyphCache::image(): not implemented by derived class " , ) ;
}
# ifdef MAGNUM_BUILD_DEPRECATED
void AbstractGlyphCache : : setImage ( const Vector2i & offset , const ImageView2D & image ) {
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
State & state = * _state ;
CORRADE_ASSERT ( state . image . size ( ) . z ( ) = = 1 ,
" Text::AbstractGlyphCache::setImage(): can't be used on an array glyph cache " , ) ;
CORRADE_ASSERT ( ( offset > = Vector2i { } & & offset + image . size ( ) < = state . image . size ( ) . xy ( ) ) . all ( ) ,
" Text::AbstractGlyphCache::setImage(): " < < Range2Di : : fromSize ( offset , image . size ( ) ) < < " out of range for glyph cache of size " < < state . image . size ( ) . xy ( ) , ) ;
CORRADE_ASSERT ( image . format ( ) = = state . image . format ( ) ,
" Text::AbstractGlyphCache::setImage(): expected " < < state . image . format ( ) < < " but got " < < image . format ( ) , ) ;
const Containers : : StridedArrayView3D < const char > src = image . pixels ( ) ;
Utility : : copy ( src ,
state . image . pixels ( ) [ 0 ] . sliceSize ( { std : : size_t ( offset . y ( ) ) ,
std : : size_t ( offset . x ( ) ) ,
0 } , src . size ( ) ) ) ;
flushImage ( Range2Di : : fromSize ( offset , image . size ( ) ) ) ;
}
# endif
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
Image3D AbstractGlyphCache : : processedImage ( ) {
CORRADE_ASSERT ( features ( ) > = GlyphCacheFeature : : ProcessedImageDownload ,
" Text::AbstractGlyphCache::processedImage(): feature not supported " , Image3D { PixelFormat : : R8Unorm } ) ;
return doProcessedImage ( ) ;
}
Image3D AbstractGlyphCache : : doProcessedImage ( ) {
CORRADE_ASSERT_UNREACHABLE ( " Text::AbstractGlyphCache::processedImage(): feature advertised but not implemented " , Image3D { PixelFormat : : R8Unorm } ) ;
}
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
UnsignedInt AbstractGlyphCache : : glyphId ( const UnsignedInt fontId , const UnsignedInt fontGlyphId ) const {
const State & state = * _state ;
CORRADE_DEBUG_ASSERT ( fontId < state . fonts . size ( ) - 1 ,
" Text::AbstractGlyphCache::glyphId(): index " < < fontId < < " out of range for " < < state . fonts . size ( ) - 1 < < " fonts " , { } ) ;
const UnsignedInt fontOffset = state . fonts [ fontId ] . offset ;
CORRADE_DEBUG_ASSERT ( fontGlyphId < state . fonts [ fontId + 1 ] . offset - fontOffset ,
" Text::AbstractGlyphCache::glyphId(): index " < < fontGlyphId < < " out of range for " < < state . fonts [ fontId + 1 ] . offset - fontOffset < < " glyphs in font " < < fontId , { } ) ;
return state . fontGlyphMapping [ fontOffset + fontGlyphId ] ;
}
void AbstractGlyphCache : : glyphIdsInto ( const UnsignedInt fontId , const Containers : : StridedArrayView1D < const UnsignedInt > & fontGlyphIds , const Containers : : StridedArrayView1D < UnsignedInt > & glyphIds ) const {
CORRADE_ASSERT ( fontGlyphIds . size ( ) = = glyphIds . size ( ) ,
" Text::AbstractGlyphCache::glyphIdsInto(): expected fontGlyphIds and glyphIds views to have the same size but got " < < fontGlyphIds . size ( ) < < " and " < < glyphIds . size ( ) , ) ;
const State & state = * _state ;
CORRADE_ASSERT ( fontId < state . fonts . size ( ) - 1 ,
" Text::AbstractGlyphCache::glyphIdsInto(): index " < < fontId < < " out of range for " < < state . fonts . size ( ) - 1 < < " fonts " , ) ;
const UnsignedInt fontOffset = state . fonts [ fontId ] . offset ;
# ifndef CORRADE_NO_DEBUG_ASSERT
const UnsignedInt fontGlyphCount = state . fonts [ fontId + 1 ] . offset - fontOffset ;
# endif
for ( std : : size_t i = 0 ; i ! = fontGlyphIds . size ( ) ; + + i ) {
const UnsignedInt fontGlyphId = fontGlyphIds [ i ] ;
CORRADE_DEBUG_ASSERT ( fontGlyphId < fontGlyphCount ,
" Text::AbstractGlyphCache::glyphIdsInto(): glyph " < < i < < " index " < < fontGlyphId < < " out of range for " < < fontGlyphCount < < " glyphs in font " < < fontId , ) ;
glyphIds [ i ] = state . fontGlyphMapping [ fontOffset + fontGlyphId ] ;
}
}
void AbstractGlyphCache : : glyphIdsInto ( const UnsignedInt fontId , const std : : initializer_list < UnsignedInt > fontGlyphIds , const Containers : : StridedArrayView1D < UnsignedInt > & glyphIds ) const {
return glyphIdsInto ( fontId , Containers : : arrayView ( fontGlyphIds ) , glyphIds ) ;
}
Containers : : StridedArrayView1D < const Vector2i > AbstractGlyphCache : : glyphOffsets ( ) const {
return stridedArrayView ( _state - > glyphs ) . slice ( & Containers : : Triple < Vector2i , Int , Range2Di > : : first ) ;
}
Containers : : StridedArrayView1D < const Int > AbstractGlyphCache : : glyphLayers ( ) const {
return stridedArrayView ( _state - > glyphs ) . slice ( & Containers : : Triple < Vector2i , Int , Range2Di > : : second ) ;
}
Containers : : StridedArrayView1D < const Range2Di > AbstractGlyphCache : : glyphRectangles ( ) const {
return stridedArrayView ( _state - > glyphs ) . slice ( & Containers : : Triple < Vector2i , Int , Range2Di > : : third ) ;
}
Containers : : Triple < Vector2i , Int , Range2Di > AbstractGlyphCache : : glyph ( const UnsignedInt fontId , const UnsignedInt fontGlyphId ) const {
const State & state = * _state ;
CORRADE_DEBUG_ASSERT ( fontId < state . fonts . size ( ) - 1 ,
" Text::AbstractGlyphCache::glyph(): index " < < fontId < < " out of range for " < < state . fonts . size ( ) - 1 < < " fonts " , { } ) ;
const UnsignedInt fontOffset = state . fonts [ fontId ] . offset ;
CORRADE_DEBUG_ASSERT ( fontGlyphId < state . fonts [ fontId + 1 ] . offset - fontOffset ,
" Text::AbstractGlyphCache::glyph(): index " < < fontGlyphId < < " out of range for " < < state . fonts [ fontId + 1 ] . offset - fontOffset < < " glyphs in font " < < fontId , { } ) ;
return state . glyphs [ state . fontGlyphMapping [ fontOffset + fontGlyphId ] ] ;
}
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
Containers : : Triple < Vector2i , Int , Range2Di > AbstractGlyphCache : : glyph ( const UnsignedInt glyphId ) const {
const State & state = * _state ;
CORRADE_DEBUG_ASSERT ( glyphId < state . glyphs . size ( ) ,
" Text::AbstractGlyphCache::glyph(): index " < < glyphId < < " out of range for " < < state . glyphs . size ( ) < < " glyphs " , { } ) ;
return state . glyphs [ glyphId ] ;
}
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
# ifdef MAGNUM_BUILD_DEPRECATED
std : : pair < Vector2i , Range2Di > AbstractGlyphCache : : operator [ ] ( const UnsignedInt glyphId ) const {
const State & state = * _state ;
CORRADE_ASSERT ( state . image . size ( ) . z ( ) = = 1 ,
" Text::AbstractGlyphCache::operator[](): can't be used on an array glyph cache " , { } ) ;
const Containers : : Triple < Vector2i , Int , Range2Di > out =
glyphId & & glyphId < state . fonts [ 1 ] . offset ? glyph ( 0 , glyphId ) : glyph ( 0 ) ;
return { out . first ( ) , out . third ( ) } ;
}
Text: rework AbstractGlyphCache for better flexibility and efficiency.
The class now supports incremental filling, multiple fonts, texture
arrays, removes all reliance on STL containers and is finally properly
documented.
To avoid complete breakage of every use, as much as possible was kept as
deprecated APIs -- in particular the reserve() with the nasty
std::vectors, the insert() that assumes a 2D cache and a single font
and textureSize() that returns a 2D vector. Those behave the same as
before, but will assert if the cache is an array or contains more than
one font.
On the other hand, begin() / end() access with std::unordered_map iterators
(ew!) was removed as the internals simply aren't a hashmap anymore. The
image() that returned an Image2D is now used to fill the glyph cache
instead of querying its potentially processed contents, and returns a
MutableImageView3D. I considered keeping it and adding sourceImage()
instead, but such naming turned out to be too inconsistent. For querying
processed image data (such as with the distance field cache) there's a
new processedImage() query, guarded by new GlyphCacheFeature bits -- if
both ImageProcessing and ProcessedImageDownload is set, it can be used
to retrieve the processed image (so, similar as ImageDownload was
before), and if neither is set, the cache contents are queryable
directly through image(), without needing any special support from
the GPU API.
Existing code is updated only in the minimal way possible to ensure that
no serious breakage was introduced by reimplementing the deprecated APIs
on top of the new backend. Porting away from deprecated APIs will be
done in next commits. The GlyphCache and DistanceFieldGlyphCache have
their public API kept intact for now, as a similar rework will be needed
for them as well.
Additionally, the MagnumFont and MagnumFontConverter plugins aren't
compiling yet as they require substantial changes to deal with the new
glyph cache features. That is not the case with other plugins in the
magnum-plugins repository tho, for those the backwards compatibility
"just works". On the other hand, since layout of the AbstractGlyphChange
changed, I'm bumping the AbstractFont plugin interface version to
force-trigger a rebuild of dependent projects. Because I ran a stale
magnum-player binary, it worked without crashing or GL errors but just
didn't show ANY text whatsoever due to ABI differences, and I wasted
some precious minutes before realizing that a simple rebuild would fix
it.
3 years ago
# endif
} }