Merge pull request #1294 from shun-iwasawa/typetool_using_qt
Enable Type Tool in OSX
This commit is contained in:
commit
da1fe046a8
7 changed files with 57 additions and 1943 deletions
|
@ -1,802 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
#ifndef __LP64__
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include "tmathutil.h"
|
|
||||||
#include "tdebugmessage.h"
|
|
||||||
#include "tfont.h"
|
|
||||||
#include "tstroke.h"
|
|
||||||
#include "tcurves.h"
|
|
||||||
#include "tconvert.h"
|
|
||||||
#include "tvectorimage.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
//----------------------------------------- structures
|
|
||||||
//-------------------------------------------------------------------
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Float32Point origin; // The origin of the current glyph
|
|
||||||
Boolean first; // Keeps track of which segment is first in a glyph
|
|
||||||
Float32Point
|
|
||||||
current; // The current pen position (used to filter degenerate cases)
|
|
||||||
|
|
||||||
float adv;
|
|
||||||
TVectorImageP m_image;
|
|
||||||
std::vector<TThickPoint> m_points;
|
|
||||||
|
|
||||||
} MyCurveCallbackData;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ATSGlyphRef glyphID; // The glyphID. This is simply an index into a table in
|
|
||||||
// the font.
|
|
||||||
Float32Point relativeOrigin; // The origin of this glyph -- relative to the
|
|
||||||
// origin of the line.
|
|
||||||
} MyGlyphRecord;
|
|
||||||
|
|
||||||
//-----------------------------------------
|
|
||||||
// callback---------------------------------------------------------------------
|
|
||||||
|
|
||||||
OSStatus MyQuadraticLineProc(const Float32Point *pt1, const Float32Point *pt2,
|
|
||||||
void *callBackDataPtr) {
|
|
||||||
/*
|
|
||||||
// Adjust the points according to the glyph origin
|
|
||||||
float x1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt1->x;
|
|
||||||
float y1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt1->y;
|
|
||||||
float x2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt2->x;
|
|
||||||
float y2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt2->y;
|
|
||||||
*/
|
|
||||||
|
|
||||||
MyCurveCallbackData *data = (MyCurveCallbackData *)callBackDataPtr;
|
|
||||||
|
|
||||||
if (data->m_points.empty())
|
|
||||||
data->m_points.push_back(TThickPoint(pt1->x, pt1->y, 0));
|
|
||||||
// else
|
|
||||||
// assert(isAlmostEqual(pt1 e back)
|
|
||||||
|
|
||||||
TThickPoint lastPoint = TThickPoint(pt2->x, pt2->y, 0);
|
|
||||||
data->m_points.push_back((data->m_points.back() + lastPoint) * 0.5);
|
|
||||||
data->m_points.push_back(lastPoint);
|
|
||||||
|
|
||||||
return noErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSStatus MyQuadraticCurveProc(const Float32Point *pt1,
|
|
||||||
const Float32Point *controlPt,
|
|
||||||
const Float32Point *pt2, void *callBackDataPtr) {
|
|
||||||
/*
|
|
||||||
// Adjust the points according to the glyph origin
|
|
||||||
float x1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt1->x;
|
|
||||||
float y1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt1->y;
|
|
||||||
float x2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt2->x;
|
|
||||||
float y2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt2->y;
|
|
||||||
float cpx = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + controlPt->x;
|
|
||||||
float cpy = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + controlPt->y;
|
|
||||||
*/
|
|
||||||
MyCurveCallbackData *data = (MyCurveCallbackData *)callBackDataPtr;
|
|
||||||
|
|
||||||
if (data->m_points.empty())
|
|
||||||
data->m_points.push_back(TThickPoint(pt1->x, pt1->y, 0));
|
|
||||||
// else
|
|
||||||
// assert(isAlmostEqual(pt1 e back)
|
|
||||||
|
|
||||||
data->m_points.push_back(TThickPoint(controlPt->x, controlPt->y, 0));
|
|
||||||
data->m_points.push_back(TThickPoint(pt2->x, pt2->y, 0));
|
|
||||||
|
|
||||||
return noErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSStatus MyQuadraticNewPathProc(void *callBackDataPtr) {
|
|
||||||
assert(((MyCurveCallbackData *)callBackDataPtr)->m_points.empty());
|
|
||||||
return noErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSStatus MyQuadraticClosePathProc(void *callBackDataPtr) {
|
|
||||||
MyCurveCallbackData *data = (MyCurveCallbackData *)callBackDataPtr;
|
|
||||||
|
|
||||||
assert(
|
|
||||||
data->m_points.size() >= 3 &&
|
|
||||||
data->m_points.size() &
|
|
||||||
1); // il numero di punti di controllo devono essere dispari e >= 3
|
|
||||||
|
|
||||||
TStroke *stroke = new TStroke(data->m_points);
|
|
||||||
stroke->setSelfLoop(true);
|
|
||||||
|
|
||||||
data->m_points.clear();
|
|
||||||
data->m_image->addStroke(stroke);
|
|
||||||
|
|
||||||
return noErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void GetGlyphIDsAndPositions(ATSUTextLayout iLayout, UniCharArrayOffset iStart,
|
|
||||||
UniCharCount iLength,
|
|
||||||
MyGlyphRecord **oGlyphRecordArray,
|
|
||||||
ItemCount *oNumGlyphs) {
|
|
||||||
// This block of code uses the new Direct Access APIs, which are only
|
|
||||||
// available on Mac OS X 10.2 and later systems
|
|
||||||
//
|
|
||||||
|
|
||||||
ATSLayoutRecord *layoutRecords;
|
|
||||||
ItemCount numRecords;
|
|
||||||
Fixed *deltaYs;
|
|
||||||
ItemCount numDeltaYs;
|
|
||||||
unsigned int i;
|
|
||||||
OSStatus status;
|
|
||||||
|
|
||||||
// Get the arrays of glyph information
|
|
||||||
status = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(
|
|
||||||
iLayout, iStart, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
|
|
||||||
(void **)&layoutRecords, &numRecords);
|
|
||||||
assert(status == noErr);
|
|
||||||
|
|
||||||
status = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(
|
|
||||||
iLayout, iStart, kATSUDirectDataBaselineDeltaFixedArray,
|
|
||||||
(void **)&deltaYs, &numDeltaYs);
|
|
||||||
assert(status == noErr);
|
|
||||||
|
|
||||||
// Build the array of MyGlyphRecords
|
|
||||||
*oGlyphRecordArray =
|
|
||||||
(MyGlyphRecord *)malloc(numRecords * sizeof(MyGlyphRecord));
|
|
||||||
*oNumGlyphs = numRecords;
|
|
||||||
|
|
||||||
for (i = 0; i < *oNumGlyphs; i++) {
|
|
||||||
// Fill in the glyphID
|
|
||||||
(*oGlyphRecordArray)[i].glyphID = layoutRecords[i].glyphID;
|
|
||||||
|
|
||||||
// Set up the relative origin of the glyph
|
|
||||||
//
|
|
||||||
// The real position is the x coordinate of the glyph, relative to the
|
|
||||||
// beginning of the line
|
|
||||||
// The baseline delta (deltaY), if any, is the y coordinate of the glyph,
|
|
||||||
// relative to the baseline
|
|
||||||
//
|
|
||||||
(*oGlyphRecordArray)[i].relativeOrigin.x = Fix2X(layoutRecords[i].realPos);
|
|
||||||
|
|
||||||
if (deltaYs == NULL) {
|
|
||||||
(*oGlyphRecordArray)[i].relativeOrigin.y = 0.0;
|
|
||||||
} else {
|
|
||||||
(*oGlyphRecordArray)[i].relativeOrigin.y = 0.0 - Fix2X(deltaYs[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free the arrays of glyph information
|
|
||||||
if (deltaYs != NULL) {
|
|
||||||
status = ATSUDirectReleaseLayoutDataArrayPtr(
|
|
||||||
NULL, kATSUDirectDataBaselineDeltaFixedArray, (void **)&deltaYs);
|
|
||||||
assert(status == noErr);
|
|
||||||
}
|
|
||||||
status = ATSUDirectReleaseLayoutDataArrayPtr(
|
|
||||||
NULL, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
|
|
||||||
(void **)&layoutRecords);
|
|
||||||
assert(status == noErr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawQuadratics(ATSUTextLayout iLayout, ATSUStyle iStyle,
|
|
||||||
UniCharArrayOffset start, UniCharCount length,
|
|
||||||
MyCurveCallbackData &data) {
|
|
||||||
// boh ----------------
|
|
||||||
Fixed penX = 0;
|
|
||||||
Fixed penY = 0;
|
|
||||||
// -------------------
|
|
||||||
|
|
||||||
MyGlyphRecord *glyphRecordArray;
|
|
||||||
ItemCount numGlyphs;
|
|
||||||
ATSQuadraticNewPathUPP newPathProc;
|
|
||||||
ATSQuadraticLineUPP lineProc;
|
|
||||||
ATSQuadraticCurveUPP curveProc;
|
|
||||||
ATSQuadraticClosePathUPP closePathProc;
|
|
||||||
|
|
||||||
OSStatus status;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
// Create the Quadratic callbacks
|
|
||||||
newPathProc = NewATSQuadraticNewPathUPP(MyQuadraticNewPathProc);
|
|
||||||
lineProc = NewATSQuadraticLineUPP(MyQuadraticLineProc);
|
|
||||||
curveProc = NewATSQuadraticCurveUPP(MyQuadraticCurveProc);
|
|
||||||
closePathProc = NewATSQuadraticClosePathUPP(MyQuadraticClosePathProc);
|
|
||||||
|
|
||||||
// Get the array of glyph information
|
|
||||||
GetGlyphIDsAndPositions(iLayout, start, length, &glyphRecordArray,
|
|
||||||
&numGlyphs);
|
|
||||||
|
|
||||||
// Loop over all the glyphs
|
|
||||||
for (i = 0; i < numGlyphs; i++) {
|
|
||||||
// Set up the absolute origin of the glyph
|
|
||||||
data.origin.x = Fix2X(penX) + glyphRecordArray[i].relativeOrigin.x;
|
|
||||||
data.origin.y = Fix2X(penY) + glyphRecordArray[i].relativeOrigin.y;
|
|
||||||
|
|
||||||
// Reset state for quadratic drawing (the callbacks only do a MoveTo on the
|
|
||||||
// very first segment)
|
|
||||||
data.first = true;
|
|
||||||
|
|
||||||
// If this is a deleted glyph (-1), don't draw it. Otherwise, go ahead.
|
|
||||||
if (glyphRecordArray[i].glyphID != kATSDeletedGlyphcode) {
|
|
||||||
status = ATSUGlyphGetQuadraticPaths(iStyle, glyphRecordArray[i].glyphID,
|
|
||||||
newPathProc, lineProc, curveProc,
|
|
||||||
closePathProc, &data, &status);
|
|
||||||
assert(status == noErr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Free the array of glyph information
|
|
||||||
free(glyphRecordArray);
|
|
||||||
|
|
||||||
// Dispose of the Quadratic callbacks
|
|
||||||
|
|
||||||
DisposeATSQuadraticNewPathUPP(newPathProc);
|
|
||||||
DisposeATSQuadraticLineUPP(lineProc);
|
|
||||||
DisposeATSQuadraticCurveUPP(curveProc);
|
|
||||||
DisposeATSQuadraticClosePathUPP(closePathProc);
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
struct TFont::Impl {
|
|
||||||
bool m_hasKerning;
|
|
||||||
int m_hasVertical;
|
|
||||||
|
|
||||||
// KerningPairs m_kerningPairs;
|
|
||||||
|
|
||||||
ATSUStyle m_style;
|
|
||||||
ATSUFontID m_fontId;
|
|
||||||
ATSUTextLayout m_layout;
|
|
||||||
Fixed m_size;
|
|
||||||
int m_ascender;
|
|
||||||
int m_descender;
|
|
||||||
|
|
||||||
Impl(ATSUFontID fontId, int size);
|
|
||||||
~Impl();
|
|
||||||
|
|
||||||
// void getChar();
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
TFont::TFont(ATSUFontID fontId, int size) { m_pimpl = new Impl(fontId, size); }
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
TFont::~TFont() { delete m_pimpl; }
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
TFont::Impl::Impl(ATSUFontID fontId, int size)
|
|
||||||
: m_fontId(fontId), m_size(Long2Fix(size)) {
|
|
||||||
OSStatus status;
|
|
||||||
|
|
||||||
long response;
|
|
||||||
status = Gestalt(gestaltATSUFeatures, &response);
|
|
||||||
assert(response & gestaltATSUDirectAccess);
|
|
||||||
|
|
||||||
status = ATSUCreateStyle(&m_style);
|
|
||||||
assert(status == noErr);
|
|
||||||
|
|
||||||
ATSUAttributeTag tags[2];
|
|
||||||
ByteCount sizes[2];
|
|
||||||
ATSUAttributeValuePtr values[2];
|
|
||||||
|
|
||||||
tags[0] = kATSUFontTag;
|
|
||||||
sizes[0] = sizeof(ATSUFontID);
|
|
||||||
values[0] = &fontId;
|
|
||||||
|
|
||||||
tags[1] = kATSUSizeTag;
|
|
||||||
sizes[1] = sizeof(Fixed);
|
|
||||||
values[1] = &m_size;
|
|
||||||
|
|
||||||
status = ATSUSetAttributes(m_style, 2, tags, sizes, values);
|
|
||||||
// assert(status==noErr);
|
|
||||||
|
|
||||||
UniChar dummyStr[] = {'H', 'e', 'l', 'l', 'o'};
|
|
||||||
UniCharCount length = sizeof(dummyStr) / sizeof(UniChar);
|
|
||||||
|
|
||||||
status = ATSUCreateTextLayoutWithTextPtr(dummyStr, kATSUFromTextBeginning,
|
|
||||||
kATSUToTextEnd, length, 1, &length,
|
|
||||||
&m_style, &m_layout);
|
|
||||||
// assert(status==noErr);
|
|
||||||
|
|
||||||
ATSTrapezoid glyphBounds;
|
|
||||||
status =
|
|
||||||
ATSUGetGlyphBounds(m_layout, 0, 0, kATSUFromTextBeginning, kATSUToTextEnd,
|
|
||||||
kATSUseFractionalOrigins, 1, &glyphBounds, NULL);
|
|
||||||
|
|
||||||
m_ascender = -FixedToInt(glyphBounds.upperLeft.y);
|
|
||||||
assert(m_ascender > 0);
|
|
||||||
m_descender = -FixedToInt(glyphBounds.lowerLeft.y);
|
|
||||||
assert(m_descender < 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
TFont::Impl::~Impl() {}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
TPoint TFont::drawChar(TVectorImageP &image, wchar_t charcode,
|
|
||||||
wchar_t nextCharCode) const {
|
|
||||||
OSStatus status;
|
|
||||||
|
|
||||||
UniChar subString[2];
|
|
||||||
subString[0] = charcode;
|
|
||||||
subString[1] = 0 /*nextCharCode*/;
|
|
||||||
UniCharCount length = sizeof(subString) / sizeof(UniChar);
|
|
||||||
|
|
||||||
status = ATSUCreateTextLayoutWithTextPtr(
|
|
||||||
subString, kATSUFromTextBeginning, kATSUToTextEnd, length, 1, &length,
|
|
||||||
&(m_pimpl->m_style), &(m_pimpl->m_layout));
|
|
||||||
assert(status == noErr);
|
|
||||||
|
|
||||||
MyCurveCallbackData data;
|
|
||||||
data.m_image = image;
|
|
||||||
|
|
||||||
drawQuadratics(m_pimpl->m_layout, m_pimpl->m_style, kATSUFromTextBeginning,
|
|
||||||
kATSUToTextEnd, data);
|
|
||||||
image->transform(TScale(1, -1));
|
|
||||||
|
|
||||||
image->group(0, image->getStrokeCount());
|
|
||||||
|
|
||||||
return getDistance(charcode, nextCharCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
void appDrawChar(TRasterGR8P &outImage, TFont::Impl *pimpl, wchar_t charcode) {
|
|
||||||
OSStatus status;
|
|
||||||
UniChar subString[2];
|
|
||||||
subString[0] = charcode;
|
|
||||||
subString[1] = 0;
|
|
||||||
UniCharCount length = sizeof(subString) / sizeof(UniChar);
|
|
||||||
|
|
||||||
status = ATSUCreateTextLayoutWithTextPtr(
|
|
||||||
subString, kATSUFromTextBeginning, kATSUToTextEnd, length, 1, &length,
|
|
||||||
&(pimpl->m_style), &(pimpl->m_layout));
|
|
||||||
assert(status == noErr);
|
|
||||||
|
|
||||||
ATSTrapezoid glyphBounds;
|
|
||||||
status = ATSUGetGlyphBounds(pimpl->m_layout, 0, 0, kATSUFromTextBeginning,
|
|
||||||
kATSUToTextEnd, kATSUseFractionalOrigins, 1,
|
|
||||||
&glyphBounds, NULL);
|
|
||||||
|
|
||||||
int height =
|
|
||||||
FixedToInt(glyphBounds.lowerLeft.y) - FixedToInt(glyphBounds.upperLeft.y);
|
|
||||||
int width = tmax(FixedToInt(glyphBounds.lowerRight.x),
|
|
||||||
FixedToInt(glyphBounds.upperRight.x)) -
|
|
||||||
tmin(FixedToInt(glyphBounds.lowerLeft.x),
|
|
||||||
FixedToInt(glyphBounds.upperLeft.x));
|
|
||||||
|
|
||||||
outImage = TRasterGR8P(width, height);
|
|
||||||
TPixelGR8 bgp;
|
|
||||||
bgp.value = 255;
|
|
||||||
outImage->fill(bgp);
|
|
||||||
void *data = outImage->getRawData();
|
|
||||||
|
|
||||||
CGColorSpaceRef grayColorSpace =
|
|
||||||
CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
|
|
||||||
CGContextRef gContext = CGBitmapContextCreate(
|
|
||||||
data, width, height, 8, width, grayColorSpace, kCGImageAlphaNone);
|
|
||||||
|
|
||||||
#if defined(DEBUG) || defined(_DEBUG)
|
|
||||||
|
|
||||||
int bpc = CGBitmapContextGetBitsPerComponent(gContext);
|
|
||||||
if (bpc != 8) std::cout << "BitsPerComponent: " << bpc << std::endl;
|
|
||||||
|
|
||||||
int bpp = CGBitmapContextGetBitsPerPixel(gContext);
|
|
||||||
if (bpp != 8) std::cout << "BitsPerPixel: " << bpp << std::endl;
|
|
||||||
|
|
||||||
int bytesPerRow = CGBitmapContextGetBytesPerRow(gContext);
|
|
||||||
int newWidth = CGBitmapContextGetWidth(gContext);
|
|
||||||
if (bytesPerRow != width || newWidth != width)
|
|
||||||
std::cout << "BytesPerRow: " << bytesPerRow << " Old width= " << width
|
|
||||||
<< " New width= " << newWidth << std::endl;
|
|
||||||
|
|
||||||
int newHeight = CGBitmapContextGetHeight(gContext);
|
|
||||||
if (newHeight != height)
|
|
||||||
std::cout << " Old height= " << height << " New height= " << newHeight
|
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
assert(CGBitmapContextGetColorSpace(gContext) == grayColorSpace);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ATSUAttributeTag tags[1];
|
|
||||||
ByteCount sizes[1];
|
|
||||||
ATSUAttributeValuePtr values[1];
|
|
||||||
|
|
||||||
tags[0] = kATSUCGContextTag;
|
|
||||||
sizes[0] = sizeof(CGContextRef);
|
|
||||||
values[0] = &gContext;
|
|
||||||
status = ATSUSetLayoutControls(pimpl->m_layout, 1, tags, sizes, values);
|
|
||||||
assert(status == noErr);
|
|
||||||
|
|
||||||
ATSUDrawText(pimpl->m_layout, kATSUFromTextBeginning, kATSUToTextEnd, 0,
|
|
||||||
glyphBounds.lowerLeft.y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
TPoint TFont::drawChar(TRasterGR8P &outImage, TPoint &unused, wchar_t charcode,
|
|
||||||
wchar_t nextCharCode) const {
|
|
||||||
appDrawChar(outImage, m_pimpl, charcode);
|
|
||||||
outImage->yMirror();
|
|
||||||
return getDistance(charcode, nextCharCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
TPoint TFont::drawChar(TRasterCM32P &outImage, TPoint &unused, int inkId,
|
|
||||||
wchar_t charcode, wchar_t nextCharCode) const {
|
|
||||||
TRasterGR8P grayAppImage;
|
|
||||||
appDrawChar(grayAppImage, m_pimpl, charcode);
|
|
||||||
|
|
||||||
int lx = grayAppImage->getLx();
|
|
||||||
int ly = grayAppImage->getLy();
|
|
||||||
|
|
||||||
outImage = TRasterCM32P(lx, ly);
|
|
||||||
|
|
||||||
assert(TPixelCM32::getMaxTone() == 255);
|
|
||||||
TPixelCM32 bgColor(0, 0, TPixelCM32::getMaxTone());
|
|
||||||
grayAppImage->lock();
|
|
||||||
outImage->lock();
|
|
||||||
int ty = 0;
|
|
||||||
for (int gy = ly - 1; gy >= 0; --gy, ++ty) {
|
|
||||||
TPixelGR8 *srcPix = grayAppImage->pixels(gy);
|
|
||||||
TPixelCM32 *tarPix = outImage->pixels(ty);
|
|
||||||
for (int x = 0; x < lx; ++x) {
|
|
||||||
int tone = srcPix->value;
|
|
||||||
|
|
||||||
if (tone == 255)
|
|
||||||
*tarPix = bgColor;
|
|
||||||
else
|
|
||||||
*tarPix = TPixelCM32(inkId, 0, tone);
|
|
||||||
|
|
||||||
++srcPix;
|
|
||||||
++tarPix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
grayAppImage->unlock();
|
|
||||||
outImage->unlock();
|
|
||||||
|
|
||||||
return getDistance(charcode, nextCharCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
TPoint TFont::getDistance(wchar_t firstChar, wchar_t secondChar) const {
|
|
||||||
OSStatus status;
|
|
||||||
UniChar subString[2];
|
|
||||||
subString[0] = firstChar;
|
|
||||||
subString[1] = secondChar;
|
|
||||||
UniCharCount length = sizeof(subString) / sizeof(UniChar);
|
|
||||||
|
|
||||||
status = ATSUCreateTextLayoutWithTextPtr(
|
|
||||||
subString, kATSUFromTextBeginning, kATSUToTextEnd, length, 1, &length,
|
|
||||||
&(m_pimpl->m_style), &(m_pimpl->m_layout));
|
|
||||||
assert(status == noErr);
|
|
||||||
|
|
||||||
MyGlyphRecord *glyphRecordArray;
|
|
||||||
ItemCount numGlyphs;
|
|
||||||
|
|
||||||
// Get the array of glyph information
|
|
||||||
GetGlyphIDsAndPositions(m_pimpl->m_layout, kATSUFromTextBeginning,
|
|
||||||
kATSUToTextEnd, &glyphRecordArray, &numGlyphs);
|
|
||||||
|
|
||||||
assert(numGlyphs >= 2);
|
|
||||||
|
|
||||||
assert(glyphRecordArray[0].relativeOrigin.x == 0);
|
|
||||||
int advance = (int)(glyphRecordArray[1].relativeOrigin.x -
|
|
||||||
glyphRecordArray[0].relativeOrigin.x);
|
|
||||||
if (advance == 0) {
|
|
||||||
subString[1] = 0;
|
|
||||||
status = ATSUCreateTextLayoutWithTextPtr(
|
|
||||||
subString, kATSUFromTextBeginning, kATSUToTextEnd, length, 1, &length,
|
|
||||||
&(m_pimpl->m_style), &(m_pimpl->m_layout));
|
|
||||||
|
|
||||||
GetGlyphIDsAndPositions(m_pimpl->m_layout, kATSUFromTextBeginning,
|
|
||||||
kATSUToTextEnd, &glyphRecordArray, &numGlyphs);
|
|
||||||
advance = (int)(glyphRecordArray[1].relativeOrigin.x -
|
|
||||||
glyphRecordArray[0].relativeOrigin.x);
|
|
||||||
}
|
|
||||||
return TPoint(advance, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
int TFont::getMaxHeight() const {
|
|
||||||
return m_pimpl->m_ascender - m_pimpl->m_descender;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
int TFont::getMaxWidth() const {
|
|
||||||
assert(!"not implemented yet");
|
|
||||||
return 100;
|
|
||||||
}
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
int TFont::getLineAscender() const { return m_pimpl->m_ascender; }
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
int TFont::getLineDescender() const { return m_pimpl->m_descender; }
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
bool TFont::hasKerning() const { return true; }
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
bool TFont::hasVertical() const { return false; }
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
typedef std::map<std::string, ATSUFontID> FontFamily;
|
|
||||||
|
|
||||||
typedef std::map<std::string, FontFamily> FamilyMap;
|
|
||||||
|
|
||||||
struct TFontManager::Impl {
|
|
||||||
FamilyMap m_families;
|
|
||||||
bool m_loaded;
|
|
||||||
ATSUFontID m_currentAtsuFontId;
|
|
||||||
TFont *m_currentFont;
|
|
||||||
wstring m_currentFamily;
|
|
||||||
wstring m_currentTypeface;
|
|
||||||
int m_size;
|
|
||||||
|
|
||||||
Impl()
|
|
||||||
: m_currentAtsuFontId(0), m_currentFont(0), m_loaded(false), m_size(70) {}
|
|
||||||
|
|
||||||
bool setFontName(ATSUFontID fontId, int platform, int script, int lang);
|
|
||||||
bool addFont(ATSUFontID);
|
|
||||||
void loadFontNames();
|
|
||||||
bool setFont(std::wstring family, std::wstring style);
|
|
||||||
};
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
bool TFontManager::Impl::setFontName(ATSUFontID fontId, int platform,
|
|
||||||
int script, int lang) {
|
|
||||||
ByteCount oActualNameLength;
|
|
||||||
ItemCount oFontCount;
|
|
||||||
OSStatus status;
|
|
||||||
|
|
||||||
char *buffer = 0;
|
|
||||||
char *buffer2 = 0;
|
|
||||||
|
|
||||||
// chiedo la lunhezza del Full Family Name per allocare il buffer
|
|
||||||
status = ATSUFindFontName(fontId, kFontFullName, platform, script, lang, 0, 0,
|
|
||||||
&oActualNameLength, 0);
|
|
||||||
|
|
||||||
if (status != noErr || oActualNameLength <= 1) return false;
|
|
||||||
|
|
||||||
buffer = new char[oActualNameLength + 1];
|
|
||||||
// chiedo il Full Family Name
|
|
||||||
status = ATSUFindFontName(fontId, kFontFullName, platform, script, lang,
|
|
||||||
oActualNameLength, buffer, &oActualNameLength,
|
|
||||||
&oFontCount);
|
|
||||||
|
|
||||||
if (status != noErr || oActualNameLength <= 1 || buffer[0] == '\0') {
|
|
||||||
delete[] buffer;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
buffer[oActualNameLength] = '\0';
|
|
||||||
|
|
||||||
//-------------------
|
|
||||||
|
|
||||||
// chiedo la lunhezza del Typeface Name per allocare il buffer
|
|
||||||
status = ATSUFindFontName(fontId, kFontStyleName, platform, script, lang, 0,
|
|
||||||
0, &oActualNameLength, 0);
|
|
||||||
|
|
||||||
if (status != noErr || oActualNameLength <= 1) {
|
|
||||||
delete[] buffer;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
buffer2 = new char[oActualNameLength + 1];
|
|
||||||
|
|
||||||
// chiedo il Typeface Name
|
|
||||||
status = ATSUFindFontName(fontId, kFontStyleName, platform, script, lang,
|
|
||||||
oActualNameLength, buffer2, &oActualNameLength,
|
|
||||||
&oFontCount);
|
|
||||||
|
|
||||||
if (status != noErr || oActualNameLength <= 1 || buffer2[0] == '\0') {
|
|
||||||
delete[] buffer;
|
|
||||||
delete[] buffer2;
|
|
||||||
return false;
|
|
||||||
} else
|
|
||||||
buffer2[oActualNameLength] = '\0';
|
|
||||||
|
|
||||||
string s_family(buffer);
|
|
||||||
FontFamily &family = m_families[s_family];
|
|
||||||
family[string(buffer2)] = fontId;
|
|
||||||
delete[] buffer;
|
|
||||||
delete[] buffer2;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TFontManager::Impl::addFont(ATSUFontID fontId) {
|
|
||||||
int platform, script, lang;
|
|
||||||
|
|
||||||
// per ottimizzare, ciclo solo sui valori
|
|
||||||
// piu' comuni
|
|
||||||
for (lang = -1; lang <= 0; lang++)
|
|
||||||
for (platform = -1; platform <= 1; platform++)
|
|
||||||
for (script = -1; script <= 0; script++)
|
|
||||||
if (setFontName(fontId, platform, script, lang)) return true;
|
|
||||||
|
|
||||||
// poi li provo tutti
|
|
||||||
for (lang = -1; lang <= 139; lang++)
|
|
||||||
for (script = -1; script <= 32; script++)
|
|
||||||
for (platform = -1; platform <= 4; platform++) {
|
|
||||||
// escludo quelli nel tri-ciclo for precedente.
|
|
||||||
// Purtoppo si deve fare cosi:
|
|
||||||
// non si puo' fare partendo con indici piu' alti nei cicli for!
|
|
||||||
if (-1 <= lang && lang <= 0 && -1 <= script && script <= 0 &&
|
|
||||||
-1 <= platform && platform <= 1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (setFontName(fontId, platform, script, lang)) return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TFontManager::Impl::loadFontNames() {
|
|
||||||
if (m_loaded) return;
|
|
||||||
|
|
||||||
ItemCount oFontCount, fontCount;
|
|
||||||
ATSUFontCount(&oFontCount);
|
|
||||||
fontCount = oFontCount;
|
|
||||||
ATSUFontID *oFontIDs = new ATSUFontID[fontCount];
|
|
||||||
ATSUGetFontIDs(oFontIDs, fontCount, &oFontCount);
|
|
||||||
assert(fontCount == oFontCount);
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < fontCount; i++) addFont(oFontIDs[i]);
|
|
||||||
|
|
||||||
delete[] oFontIDs;
|
|
||||||
m_loaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TFontManager::Impl::setFont(std::wstring family, std::wstring typeface) {
|
|
||||||
if (family == m_currentFamily &&
|
|
||||||
(typeface == m_currentTypeface || typeface == L""))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
FamilyMap::iterator family_it = m_families.find(toString(family));
|
|
||||||
if (family_it == m_families.end()) throw TFontCreationError();
|
|
||||||
|
|
||||||
m_currentFamily = family;
|
|
||||||
FontFamily::iterator style_it;
|
|
||||||
if (typeface == L"") {
|
|
||||||
style_it = ((*family_it).second).find(toString(m_currentTypeface));
|
|
||||||
if (style_it == (*family_it).second.end())
|
|
||||||
style_it = ((*family_it).second).begin();
|
|
||||||
|
|
||||||
typeface = toWideString(style_it->first);
|
|
||||||
} else
|
|
||||||
style_it = ((*family_it).second).find(toString(typeface));
|
|
||||||
|
|
||||||
if (style_it == (*family_it).second.end()) throw TFontCreationError();
|
|
||||||
|
|
||||||
m_currentTypeface = typeface;
|
|
||||||
m_currentAtsuFontId = (*style_it).second;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
TFontManager::TFontManager() { m_pimpl = new TFontManager::Impl(); }
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
TFontManager::~TFontManager() { delete m_pimpl; }
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
TFontManager *TFontManager::instance() {
|
|
||||||
static TFontManager theManager;
|
|
||||||
return &theManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::loadFontNames() { m_pimpl->loadFontNames(); }
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::setFamily(const wstring family) {
|
|
||||||
bool changed = m_pimpl->setFont(family, L"");
|
|
||||||
if (changed) {
|
|
||||||
delete m_pimpl->m_currentFont;
|
|
||||||
m_pimpl->m_currentFont =
|
|
||||||
new TFont(m_pimpl->m_currentAtsuFontId, m_pimpl->m_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::setTypeface(const wstring typeface) {
|
|
||||||
bool changed = m_pimpl->setFont(m_pimpl->m_currentFamily, typeface);
|
|
||||||
if (changed) {
|
|
||||||
delete m_pimpl->m_currentFont;
|
|
||||||
m_pimpl->m_currentFont =
|
|
||||||
new TFont(m_pimpl->m_currentAtsuFontId, m_pimpl->m_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::setSize(int size) {
|
|
||||||
if (m_pimpl->m_size != size) {
|
|
||||||
m_pimpl->m_size = size;
|
|
||||||
delete m_pimpl->m_currentFont;
|
|
||||||
m_pimpl->m_currentFont =
|
|
||||||
new TFont(m_pimpl->m_currentAtsuFontId, m_pimpl->m_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
wstring TFontManager::getCurrentFamily() const {
|
|
||||||
return m_pimpl->m_currentFamily;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
wstring TFontManager::getCurrentTypeface() const {
|
|
||||||
return m_pimpl->m_currentTypeface;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
TFont *TFontManager::getCurrentFont() {
|
|
||||||
if (m_pimpl->m_currentFont) return m_pimpl->m_currentFont;
|
|
||||||
|
|
||||||
if (!m_pimpl->m_currentFont) loadFontNames();
|
|
||||||
|
|
||||||
assert(!m_pimpl->m_families.empty());
|
|
||||||
setFamily(toWideString(m_pimpl->m_families.begin()->first));
|
|
||||||
|
|
||||||
return m_pimpl->m_currentFont;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::getAllFamilies(vector<wstring> &families) const {
|
|
||||||
families.clear();
|
|
||||||
families.reserve(m_pimpl->m_families.size());
|
|
||||||
|
|
||||||
FamilyMap::iterator it = m_pimpl->m_families.begin();
|
|
||||||
for (; it != m_pimpl->m_families.end(); ++it) {
|
|
||||||
families.push_back(toWideString(it->first));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::getAllTypefaces(vector<wstring> &typefaces) const {
|
|
||||||
typefaces.clear();
|
|
||||||
FamilyMap::iterator it_family =
|
|
||||||
m_pimpl->m_families.find(toString(m_pimpl->m_currentFamily));
|
|
||||||
if (it_family == m_pimpl->m_families.end()) return;
|
|
||||||
FontFamily &typefaceSet = it_family->second;
|
|
||||||
|
|
||||||
typefaces.reserve(typefaceSet.size());
|
|
||||||
FontFamily::iterator it_typeface = typefaceSet.begin();
|
|
||||||
for (; it_typeface != typefaceSet.end(); ++it_typeface) {
|
|
||||||
typefaces.push_back(toWideString(it_typeface->first));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::setVertical(bool vertical) {}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,642 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
// character_manager.cpp: implementation of the TFont class.
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "tpixelgr.h"
|
|
||||||
#include "tfont.h"
|
|
||||||
#include "tstroke.h"
|
|
||||||
//#include "tcurves.h"
|
|
||||||
#include "traster.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
//#include <tstring.h>
|
|
||||||
#include <tmathutil.h>
|
|
||||||
//#include <tdebugmessage.h>
|
|
||||||
#include "tvectorimage.h"
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
typedef map<wstring, LOGFONTW> WindowsFontTable;
|
|
||||||
typedef map<pair<unsigned short, unsigned short>, int> KerningPairs;
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
struct TFont::Impl {
|
|
||||||
bool m_hasKerning;
|
|
||||||
bool m_hasVertical;
|
|
||||||
HFONT m_font;
|
|
||||||
HDC m_hdc;
|
|
||||||
TEXTMETRICW m_metrics;
|
|
||||||
KerningPairs m_kerningPairs;
|
|
||||||
|
|
||||||
Impl(const LOGFONTW &font, HDC hdc);
|
|
||||||
~Impl();
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
TFont::TFont(const LOGFONTW &font, HDC hdc) { m_pimpl = new Impl(font, hdc); }
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
TFont::~TFont() { delete m_pimpl; }
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
TFont::Impl::Impl(const LOGFONTW &logfont, HDC hdc) : m_hdc(hdc) {
|
|
||||||
m_font = CreateFontIndirectW(&logfont);
|
|
||||||
|
|
||||||
if (!m_font) throw TFontCreationError();
|
|
||||||
|
|
||||||
HGDIOBJ hObj = SelectObject(hdc, m_font);
|
|
||||||
if (!hObj || hObj == HGDI_ERROR) throw TFontCreationError();
|
|
||||||
|
|
||||||
if (!GetTextMetricsW(hdc, &m_metrics)) throw TFontCreationError();
|
|
||||||
|
|
||||||
DWORD pairsCount = GetKerningPairsW(hdc, 0, 0);
|
|
||||||
if (pairsCount) {
|
|
||||||
m_hasKerning = true;
|
|
||||||
std::unique_ptr<KERNINGPAIR[]> tempKernPairs(new KERNINGPAIR[pairsCount]);
|
|
||||||
GetKerningPairsW(hdc, pairsCount, tempKernPairs.get());
|
|
||||||
for (UINT i = 0; i < pairsCount; i++) {
|
|
||||||
pair<unsigned short, unsigned short> key =
|
|
||||||
make_pair(tempKernPairs[i].wFirst, tempKernPairs[i].wSecond);
|
|
||||||
m_kerningPairs[key] = tempKernPairs[i].iKernAmount;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
m_hasKerning = false;
|
|
||||||
|
|
||||||
m_hasVertical = (logfont.lfFaceName)[0] == '@';
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
TFont::Impl::~Impl() {
|
|
||||||
// delete m_advances;
|
|
||||||
DeleteObject(m_font);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
inline TThickPoint toThickPoint(POINTFX point) {
|
|
||||||
double app1 = point.x.value +
|
|
||||||
((double)point.x.fract) / (std::numeric_limits<WORD>::max)();
|
|
||||||
double app2 = point.y.value +
|
|
||||||
((double)point.y.fract) / (std::numeric_limits<WORD>::max)();
|
|
||||||
return TThickPoint(app1, app2, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
TPoint TFont::drawChar(TVectorImageP &image, wchar_t charcode,
|
|
||||||
wchar_t nextCharCode) const
|
|
||||||
|
|
||||||
{
|
|
||||||
GLYPHMETRICS gm;
|
|
||||||
MAT2 mat2;
|
|
||||||
mat2.eM11.fract = 0;
|
|
||||||
mat2.eM12.fract = 0;
|
|
||||||
mat2.eM21.fract = 0;
|
|
||||||
mat2.eM22.fract = 0;
|
|
||||||
mat2.eM11.value = 1;
|
|
||||||
mat2.eM12.value = 0;
|
|
||||||
mat2.eM21.value = 0;
|
|
||||||
mat2.eM22.value = 1;
|
|
||||||
|
|
||||||
vector<TThickPoint> points;
|
|
||||||
|
|
||||||
UINT j = 0;
|
|
||||||
|
|
||||||
DWORD charMemorySize =
|
|
||||||
GetGlyphOutlineW(m_pimpl->m_hdc, charcode, GGO_NATIVE, &gm, 0, 0, &mat2);
|
|
||||||
if (charMemorySize == GDI_ERROR) {
|
|
||||||
assert(0);
|
|
||||||
return TPoint();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<char[]> lpvBuffer(new char[charMemorySize]);
|
|
||||||
|
|
||||||
charMemorySize = GetGlyphOutlineW(m_pimpl->m_hdc, charcode, GGO_NATIVE, &gm,
|
|
||||||
charMemorySize, lpvBuffer.get(), &mat2);
|
|
||||||
if (charMemorySize == GDI_ERROR) {
|
|
||||||
assert(0);
|
|
||||||
return TPoint();
|
|
||||||
}
|
|
||||||
|
|
||||||
TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)lpvBuffer.get();
|
|
||||||
|
|
||||||
while ((char *)header < (char *)lpvBuffer.get() + charMemorySize) {
|
|
||||||
points.clear();
|
|
||||||
TThickPoint startPoint = toThickPoint(header->pfxStart);
|
|
||||||
points.push_back(startPoint);
|
|
||||||
|
|
||||||
if (header->dwType != TT_POLYGON_TYPE) {
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
int memorySize = header->cb;
|
|
||||||
|
|
||||||
TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1);
|
|
||||||
|
|
||||||
while ((char *)curve < (char *)header + memorySize) {
|
|
||||||
switch (curve->wType) {
|
|
||||||
case TT_PRIM_LINE:
|
|
||||||
|
|
||||||
for (j = 0; j < curve->cpfx; j++) {
|
|
||||||
TThickPoint p0 = points.back();
|
|
||||||
TThickPoint p1 = toThickPoint(((*curve).apfx[j]));
|
|
||||||
points.push_back((p0 + p1) * 0.5);
|
|
||||||
points.push_back(p1);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TT_PRIM_QSPLINE:
|
|
||||||
|
|
||||||
for (j = 0; (int)j + 2 < curve->cpfx; j++) {
|
|
||||||
TThickPoint p1 = toThickPoint(((*curve).apfx[j]));
|
|
||||||
TThickPoint p2 = toThickPoint(((*curve).apfx[j + 1]));
|
|
||||||
|
|
||||||
points.push_back(p1);
|
|
||||||
points.push_back((p1 + p2) * 0.5);
|
|
||||||
}
|
|
||||||
points.push_back(toThickPoint(((*curve).apfx[j++])));
|
|
||||||
points.push_back(toThickPoint(((*curve).apfx[j++])));
|
|
||||||
|
|
||||||
break;
|
|
||||||
case TT_PRIM_CSPLINE:
|
|
||||||
assert(0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
curve = (TTPOLYCURVE *)(&(curve->apfx)[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
TThickPoint p0 = points.back();
|
|
||||||
if (!isAlmostZero(p0.x - startPoint.x) ||
|
|
||||||
!isAlmostZero(p0.y - startPoint.y)) {
|
|
||||||
points.push_back((p0 + startPoint) * 0.5);
|
|
||||||
points.push_back(startPoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
TStroke *stroke = new TStroke();
|
|
||||||
stroke->reshape(&(points[0]), points.size());
|
|
||||||
stroke->setSelfLoop(true);
|
|
||||||
image->addStroke(stroke);
|
|
||||||
|
|
||||||
header = (TTPOLYGONHEADER *)curve;
|
|
||||||
}
|
|
||||||
|
|
||||||
image->group(0, image->getStrokeCount());
|
|
||||||
|
|
||||||
return getDistance(charcode, nextCharCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
TPoint appDrawChar(TRasterGR8P &outImage, HDC hdc, wchar_t charcode) {
|
|
||||||
GLYPHMETRICS gm;
|
|
||||||
MAT2 mat2;
|
|
||||||
mat2.eM11.fract = 0;
|
|
||||||
mat2.eM12.fract = 0;
|
|
||||||
mat2.eM21.fract = 0;
|
|
||||||
mat2.eM22.fract = 0;
|
|
||||||
mat2.eM11.value = 1;
|
|
||||||
mat2.eM12.value = 0;
|
|
||||||
mat2.eM21.value = 0;
|
|
||||||
mat2.eM22.value = 1;
|
|
||||||
|
|
||||||
DWORD charMemorySize =
|
|
||||||
GetGlyphOutlineW(hdc, charcode, GGO_GRAY8_BITMAP, &gm, 0, 0, &mat2);
|
|
||||||
|
|
||||||
if (charMemorySize == GDI_ERROR) {
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int lx = gm.gmBlackBoxX;
|
|
||||||
int ly = gm.gmBlackBoxY;
|
|
||||||
|
|
||||||
int wrap = ((lx + 3) >> 2) << 2;
|
|
||||||
|
|
||||||
TRasterGR8P appImage = TRasterGR8P(wrap, ly);
|
|
||||||
appImage->clear();
|
|
||||||
outImage = appImage->extract(0, 0, lx - 1, ly - 1);
|
|
||||||
outImage->lock();
|
|
||||||
GetGlyphOutlineW(hdc, charcode, GGO_GRAY8_BITMAP, &gm, wrap * ly,
|
|
||||||
outImage->getRawData(), &mat2);
|
|
||||||
outImage->unlock();
|
|
||||||
TPoint glyphOrig;
|
|
||||||
glyphOrig.x = gm.gmptGlyphOrigin.x;
|
|
||||||
glyphOrig.y = gm.gmptGlyphOrigin.y;
|
|
||||||
return glyphOrig;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// valori compresi tra 0 e 64 (si si, proprio 64 e non 63: sono 65 valori)
|
|
||||||
|
|
||||||
TPoint TFont::drawChar(TRasterGR8P &outImage, TPoint &glyphOrigin,
|
|
||||||
wchar_t charcode, wchar_t nextCharCode) const {
|
|
||||||
TRasterGR8P grayAppImage;
|
|
||||||
|
|
||||||
TPoint glyphOrig = appDrawChar(grayAppImage, m_pimpl->m_hdc, charcode);
|
|
||||||
|
|
||||||
if (glyphOrig.x < 0) {
|
|
||||||
glyphOrigin.x = glyphOrig.x;
|
|
||||||
glyphOrig.x = 0;
|
|
||||||
} else
|
|
||||||
glyphOrigin.x = 0;
|
|
||||||
|
|
||||||
if (glyphOrig.y < 0) {
|
|
||||||
glyphOrigin.y = glyphOrig.y;
|
|
||||||
glyphOrig.y = 0;
|
|
||||||
} else
|
|
||||||
glyphOrigin.y = 0;
|
|
||||||
|
|
||||||
int srcLx = grayAppImage->getLx();
|
|
||||||
int srcLy = grayAppImage->getLy();
|
|
||||||
|
|
||||||
int dstLx = srcLx + glyphOrig.x;
|
|
||||||
int dstLy = getMaxHeight();
|
|
||||||
|
|
||||||
outImage = TRasterGR8P(dstLx, dstLy);
|
|
||||||
outImage->clear();
|
|
||||||
|
|
||||||
int ty = m_pimpl->m_metrics.tmDescent - 1 + glyphOrig.y;
|
|
||||||
assert(ty < dstLy);
|
|
||||||
assert(ty >= srcLy - 1);
|
|
||||||
grayAppImage->lock();
|
|
||||||
outImage->lock();
|
|
||||||
|
|
||||||
for (int sy = 0; sy < srcLy; ++sy, --ty) {
|
|
||||||
TPixelGR8 *srcPix = grayAppImage->pixels(sy);
|
|
||||||
TPixelGR8 *tarPix = outImage->pixels(ty) + glyphOrig.x;
|
|
||||||
for (int x = 0; x < srcLx; ++x) {
|
|
||||||
assert(srcPix->value < 65);
|
|
||||||
|
|
||||||
switch (srcPix->value) {
|
|
||||||
case 0:
|
|
||||||
tarPix->value = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tarPix->value = (srcPix->value << 2) - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
++srcPix;
|
|
||||||
++tarPix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
grayAppImage->unlock();
|
|
||||||
outImage->unlock();
|
|
||||||
|
|
||||||
return getDistance(charcode, nextCharCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
TPoint TFont::drawChar(TRasterCM32P &outImage, TPoint &glyphOrigin, int inkId,
|
|
||||||
wchar_t charcode, wchar_t nextCharCode) const {
|
|
||||||
TRasterGR8P grayAppImage;
|
|
||||||
TPoint glyphOrig = appDrawChar(grayAppImage, m_pimpl->m_hdc, charcode);
|
|
||||||
|
|
||||||
if (glyphOrig.x < 0) {
|
|
||||||
glyphOrigin.x = glyphOrig.x;
|
|
||||||
glyphOrig.x = 0;
|
|
||||||
} else
|
|
||||||
glyphOrigin.x = 0;
|
|
||||||
|
|
||||||
if (glyphOrig.y < 0) {
|
|
||||||
glyphOrigin.y = glyphOrig.y;
|
|
||||||
glyphOrig.y = 0;
|
|
||||||
} else
|
|
||||||
glyphOrigin.y = 0;
|
|
||||||
|
|
||||||
int srcLx = grayAppImage->getLx();
|
|
||||||
int srcLy = grayAppImage->getLy();
|
|
||||||
|
|
||||||
int dstLx = srcLx + glyphOrig.x;
|
|
||||||
int dstLy = getMaxHeight();
|
|
||||||
|
|
||||||
outImage = TRasterCM32P(dstLx, dstLy);
|
|
||||||
outImage->clear();
|
|
||||||
|
|
||||||
assert(TPixelCM32::getMaxTone() == 255);
|
|
||||||
// TPixelCM32
|
|
||||||
// bgColor(BackgroundStyle,BackgroundStyle,TPixelCM32::getMaxTone());
|
|
||||||
TPixelCM32 bgColor;
|
|
||||||
|
|
||||||
int ty = m_pimpl->m_metrics.tmDescent - 1 + glyphOrig.y;
|
|
||||||
assert(ty < dstLy);
|
|
||||||
assert(ty >= srcLy - 1);
|
|
||||||
grayAppImage->lock();
|
|
||||||
outImage->lock();
|
|
||||||
|
|
||||||
for (int sy = 0; sy < srcLy; ++sy, --ty) {
|
|
||||||
TPixelGR8 *srcPix = grayAppImage->pixels(sy);
|
|
||||||
TPixelCM32 *tarPix = outImage->pixels(ty) + glyphOrig.x;
|
|
||||||
for (int x = 0; x < srcLx; ++x) {
|
|
||||||
int tone = 256 - (srcPix->value << 2);
|
|
||||||
|
|
||||||
// grayScale ToonzImage tone Meaning
|
|
||||||
// 0 255 Bg = PurePaint
|
|
||||||
// 1 252
|
|
||||||
// ...
|
|
||||||
// 63 4
|
|
||||||
// 64 0 Fg = Pure Ink
|
|
||||||
|
|
||||||
if (tone < 0) tone = 0;
|
|
||||||
|
|
||||||
if (tone >= 255)
|
|
||||||
*tarPix = bgColor;
|
|
||||||
else
|
|
||||||
*tarPix = TPixelCM32(inkId, 0, tone); // BackgroundStyle,tone);
|
|
||||||
|
|
||||||
++srcPix;
|
|
||||||
++tarPix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
grayAppImage->unlock();
|
|
||||||
outImage->unlock();
|
|
||||||
|
|
||||||
return getDistance(charcode, nextCharCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
TPoint TFont::getDistance(wchar_t firstChar, wchar_t secondChar) const {
|
|
||||||
int advance;
|
|
||||||
BOOL result = GetCharWidth32W(m_pimpl->m_hdc, firstChar, firstChar, &advance);
|
|
||||||
assert(result);
|
|
||||||
if (m_pimpl->m_hasKerning && secondChar) {
|
|
||||||
KerningPairs::iterator it =
|
|
||||||
m_pimpl->m_kerningPairs.find(make_pair(firstChar, secondChar));
|
|
||||||
if (it != m_pimpl->m_kerningPairs.end()) {
|
|
||||||
advance += it->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TPoint(advance, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
int TFont::getMaxHeight() const { return m_pimpl->m_metrics.tmHeight; }
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
int TFont::getMaxWidth() const { return m_pimpl->m_metrics.tmMaxCharWidth; }
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
int TFont::getLineAscender() const { return m_pimpl->m_metrics.tmAscent; }
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
int TFont::getLineDescender() const { return -m_pimpl->m_metrics.tmDescent; }
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
bool TFont::hasKerning() const { return m_pimpl->m_hasKerning; }
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
bool TFont::hasVertical() const { return m_pimpl->m_hasVertical; }
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//==================== TFontManager =====================================
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
struct TFontManager::Impl {
|
|
||||||
WindowsFontTable m_families;
|
|
||||||
bool m_loaded;
|
|
||||||
|
|
||||||
LOGFONTW m_currentLogFont;
|
|
||||||
TFont *m_currentFont;
|
|
||||||
|
|
||||||
// this option is set by library user when he wants to write vertically.
|
|
||||||
// In this implementation, if m_vertical is true and the font
|
|
||||||
// has the @-version, the library use it.
|
|
||||||
bool m_vertical;
|
|
||||||
|
|
||||||
Impl() : m_loaded(false), m_currentFont(0), m_vertical(false) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
TFontManager::TFontManager() { m_pimpl = new TFontManager::Impl(); }
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
TFontManager::~TFontManager() { delete m_pimpl; }
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
TFontManager *TFontManager::instance() {
|
|
||||||
static TFontManager theManager;
|
|
||||||
return &theManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
BOOL CALLBACK EnumFamCallBack(CONST LOGFONTW *lplf, CONST TEXTMETRICW *,
|
|
||||||
DWORD FontType, LPARAM data) {
|
|
||||||
if (FontType & TRUETYPE_FONTTYPE) {
|
|
||||||
LOGFONTW newLplf = *lplf;
|
|
||||||
newLplf.lfHeight = 200;
|
|
||||||
newLplf.lfWidth = 0;
|
|
||||||
WindowsFontTable &table = *(WindowsFontTable *)data;
|
|
||||||
table[lplf->lfFaceName] = newLplf;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::loadFontNames() {
|
|
||||||
if (m_pimpl->m_loaded) return;
|
|
||||||
|
|
||||||
HDC hdc = CreateCompatibleDC(NULL);
|
|
||||||
if (!hdc) throw TFontLibraryLoadingError();
|
|
||||||
EnumFontFamiliesW(hdc, (LPCWSTR)NULL, (FONTENUMPROCW)EnumFamCallBack,
|
|
||||||
(LPARAM) & (m_pimpl->m_families));
|
|
||||||
DeleteDC(hdc);
|
|
||||||
hdc = 0;
|
|
||||||
if (m_pimpl->m_families.empty()) throw TFontLibraryLoadingError();
|
|
||||||
|
|
||||||
m_pimpl->m_loaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::setFamily(const wstring family) {
|
|
||||||
wstring userFamilyName =
|
|
||||||
((family.c_str())[0] == L'@') ? wstring(family.c_str() + 1) : family;
|
|
||||||
wstring realFamilyName = (m_pimpl->m_vertical && (family.c_str())[0] != L'@')
|
|
||||||
? L"@" + family
|
|
||||||
: family;
|
|
||||||
|
|
||||||
wstring currentFamilyName = wstring(m_pimpl->m_currentLogFont.lfFaceName);
|
|
||||||
|
|
||||||
if (currentFamilyName == realFamilyName) return;
|
|
||||||
|
|
||||||
LOGFONTW logfont;
|
|
||||||
if (m_pimpl->m_vertical) {
|
|
||||||
WindowsFontTable::iterator it = m_pimpl->m_families.find(realFamilyName);
|
|
||||||
if (it != m_pimpl->m_families.end())
|
|
||||||
logfont = it->second;
|
|
||||||
else {
|
|
||||||
it = m_pimpl->m_families.find(userFamilyName);
|
|
||||||
assert(it != m_pimpl->m_families.end());
|
|
||||||
if (it != m_pimpl->m_families.end())
|
|
||||||
logfont = it->second;
|
|
||||||
else
|
|
||||||
throw TFontCreationError();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
WindowsFontTable::iterator it = m_pimpl->m_families.find(userFamilyName);
|
|
||||||
assert(it != m_pimpl->m_families.end());
|
|
||||||
if (it != m_pimpl->m_families.end())
|
|
||||||
logfont = it->second;
|
|
||||||
else
|
|
||||||
throw TFontCreationError();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_pimpl->m_currentFont) {
|
|
||||||
logfont.lfHeight = m_pimpl->m_currentLogFont.lfHeight;
|
|
||||||
logfont.lfItalic = m_pimpl->m_currentLogFont.lfItalic;
|
|
||||||
logfont.lfWeight = m_pimpl->m_currentLogFont.lfWeight;
|
|
||||||
} else
|
|
||||||
logfont.lfHeight = 200;
|
|
||||||
|
|
||||||
try {
|
|
||||||
HDC hdc = CreateCompatibleDC(NULL);
|
|
||||||
TFont *newfont = new TFont(logfont, hdc);
|
|
||||||
delete m_pimpl->m_currentFont;
|
|
||||||
m_pimpl->m_currentFont = newfont;
|
|
||||||
m_pimpl->m_currentLogFont = logfont;
|
|
||||||
} catch (TException &) {
|
|
||||||
throw TFontCreationError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::setTypeface(const wstring typeface) {
|
|
||||||
LOGFONTW logfont = m_pimpl->m_currentLogFont;
|
|
||||||
logfont.lfItalic =
|
|
||||||
(typeface == L"Italic" || typeface == L"Bold Italic") ? TRUE : FALSE;
|
|
||||||
logfont.lfWeight =
|
|
||||||
(typeface == L"Bold" || typeface == L"Bold Italic") ? 700 : 400;
|
|
||||||
|
|
||||||
try {
|
|
||||||
HDC hdc = CreateCompatibleDC(NULL);
|
|
||||||
TFont *newfont = new TFont(logfont, hdc);
|
|
||||||
delete m_pimpl->m_currentFont;
|
|
||||||
m_pimpl->m_currentFont = newfont;
|
|
||||||
m_pimpl->m_currentLogFont = logfont;
|
|
||||||
} catch (TException &) {
|
|
||||||
throw TFontCreationError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::setSize(int size) {
|
|
||||||
LOGFONTW logfont = m_pimpl->m_currentLogFont;
|
|
||||||
logfont.lfHeight = size;
|
|
||||||
try {
|
|
||||||
HDC hdc = CreateCompatibleDC(NULL);
|
|
||||||
TFont *newfont = new TFont(logfont, hdc);
|
|
||||||
delete m_pimpl->m_currentFont;
|
|
||||||
m_pimpl->m_currentFont = newfont;
|
|
||||||
m_pimpl->m_currentLogFont = logfont;
|
|
||||||
} catch (TException &) {
|
|
||||||
throw TFontCreationError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
wstring TFontManager::getCurrentFamily() const {
|
|
||||||
wstring currentFamilyName =
|
|
||||||
(m_pimpl->m_currentLogFont.lfFaceName[0] == L'@')
|
|
||||||
? wstring(m_pimpl->m_currentLogFont.lfFaceName + 1)
|
|
||||||
: wstring(m_pimpl->m_currentLogFont.lfFaceName);
|
|
||||||
return currentFamilyName;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
wstring TFontManager::getCurrentTypeface() const {
|
|
||||||
if (m_pimpl->m_currentLogFont.lfItalic) {
|
|
||||||
if (m_pimpl->m_currentLogFont.lfWeight == 700)
|
|
||||||
return L"Bold Italic";
|
|
||||||
else
|
|
||||||
return L"Italic";
|
|
||||||
} else {
|
|
||||||
if (m_pimpl->m_currentLogFont.lfWeight == 700)
|
|
||||||
return L"Bold";
|
|
||||||
else
|
|
||||||
return L"Regular";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
TFont *TFontManager::getCurrentFont() {
|
|
||||||
if (m_pimpl->m_currentFont) return m_pimpl->m_currentFont;
|
|
||||||
|
|
||||||
if (!m_pimpl->m_currentFont) loadFontNames();
|
|
||||||
|
|
||||||
assert(!m_pimpl->m_families.empty());
|
|
||||||
setFamily(m_pimpl->m_families.begin()->first);
|
|
||||||
|
|
||||||
return m_pimpl->m_currentFont;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::getAllFamilies(vector<wstring> &families) const {
|
|
||||||
families.clear();
|
|
||||||
families.reserve(m_pimpl->m_families.size());
|
|
||||||
WindowsFontTable::iterator it = m_pimpl->m_families.begin();
|
|
||||||
for (; it != m_pimpl->m_families.end(); ++it) {
|
|
||||||
if ((it->first)[0] != L'@') families.push_back(it->first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::getAllTypefaces(vector<wstring> &typefaces) const {
|
|
||||||
typefaces.resize(4);
|
|
||||||
typefaces[0] = L"Regular";
|
|
||||||
typefaces[1] = L"Italic";
|
|
||||||
typefaces[2] = L"Bold";
|
|
||||||
typefaces[3] = L"Bold Italic";
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::setVertical(bool vertical) {
|
|
||||||
if (m_pimpl->m_vertical == vertical) return;
|
|
||||||
m_pimpl->m_vertical = vertical;
|
|
||||||
|
|
||||||
wstring currentFamilyName =
|
|
||||||
(m_pimpl->m_currentLogFont.lfFaceName[0] == L'@')
|
|
||||||
? wstring(m_pimpl->m_currentLogFont.lfFaceName + 1)
|
|
||||||
: wstring(m_pimpl->m_currentLogFont.lfFaceName);
|
|
||||||
if (vertical) currentFamilyName = L'@' + currentFamilyName;
|
|
||||||
setFamily(currentFamilyName);
|
|
||||||
}
|
|
|
@ -1,404 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
#if defined(__LP64__) && !defined(LINUX)
|
|
||||||
|
|
||||||
// Toonz includes
|
|
||||||
#include "tvectorimage.h"
|
|
||||||
#include "tstroke.h"
|
|
||||||
#include "trop.h"
|
|
||||||
|
|
||||||
// Qt includes
|
|
||||||
#include <QSharedMemory>
|
|
||||||
|
|
||||||
/*
|
|
||||||
なぜか tipc.h の
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
QDataStream& operator>>(QDataStream& ds, std::vector<T>& vec)
|
|
||||||
|
|
||||||
が T=TThickPoint でインスタンス化されようとして曖昧ですエラーになる
|
|
||||||
*/
|
|
||||||
// tipc includes
|
|
||||||
#include "tipc.h"
|
|
||||||
#include "t32bitsrv_wrap.h"
|
|
||||||
|
|
||||||
#include "tfont.h"
|
|
||||||
|
|
||||||
//**************************************************************************
|
|
||||||
// Local namespace stuff
|
|
||||||
//**************************************************************************
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
QDataStream &operator>>(QDataStream &ds, TThickPoint &p) {
|
|
||||||
return ds >> p.x >> p.y >> p.thick;
|
|
||||||
}
|
|
||||||
|
|
||||||
void readVImage(TVectorImageP &vi, tipc::Message &msg) {
|
|
||||||
std::vector<TThickPoint> strokeCPs;
|
|
||||||
|
|
||||||
// Read in all strokes
|
|
||||||
while (!msg.ds().atEnd()) {
|
|
||||||
strokeCPs.clear();
|
|
||||||
msg >> strokeCPs;
|
|
||||||
|
|
||||||
vi->addStroke(new TStroke(strokeCPs));
|
|
||||||
}
|
|
||||||
|
|
||||||
vi->group(0, vi->getStrokeCount());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
//**************************************************************************
|
|
||||||
// TFontManager Private stuff
|
|
||||||
//**************************************************************************
|
|
||||||
|
|
||||||
/*
|
|
||||||
The proxied Impl private just caches some data of the actual
|
|
||||||
background counterpart
|
|
||||||
*/
|
|
||||||
struct TFontManager::Impl {
|
|
||||||
int m_ascender;
|
|
||||||
int m_descender;
|
|
||||||
|
|
||||||
Impl() {}
|
|
||||||
~Impl() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
//**************************************************************************
|
|
||||||
// TFontManager Proxied implementation
|
|
||||||
//**************************************************************************
|
|
||||||
|
|
||||||
TFontManager::TFontManager() { m_pimpl = new TFontManager::Impl(); }
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
TFontManager::~TFontManager() { delete m_pimpl; }
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
TFontManager *TFontManager::instance() {
|
|
||||||
static TFontManager theInstance;
|
|
||||||
return &theInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
//! This function is retained from old 32-bit legacy code.
|
|
||||||
//! Its use is now forbidden - use the TFontManager directly instead.
|
|
||||||
TFont *TFontManager::getCurrentFont() {
|
|
||||||
assert(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
//!\note Throws TFontLibraryLoadingError if fonts could not be loaded
|
|
||||||
void TFontManager::loadFontNames() {
|
|
||||||
// Connect to the 32-bit background server process
|
|
||||||
QLocalSocket socket;
|
|
||||||
tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1,
|
|
||||||
t32bitsrv::srvCmdline());
|
|
||||||
|
|
||||||
tipc::Stream stream(&socket);
|
|
||||||
tipc::Message msg;
|
|
||||||
|
|
||||||
stream << (msg << QString("$FNTloadFontNames"));
|
|
||||||
if (tipc::readMessage(stream, msg) != "ok") throw TFontLibraryLoadingError();
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
//!\note Throws TFontCreationError if the font could not be created, and
|
|
||||||
//! leaves the old font as current.
|
|
||||||
void TFontManager::setFamily(const std::wstring family) {
|
|
||||||
QLocalSocket socket;
|
|
||||||
tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1,
|
|
||||||
t32bitsrv::srvCmdline());
|
|
||||||
|
|
||||||
tipc::Stream stream(&socket);
|
|
||||||
tipc::Message msg;
|
|
||||||
|
|
||||||
stream << (msg << QString("$FNTsetFamily") << family);
|
|
||||||
if (tipc::readMessage(stream, msg) != "ok") throw TFontCreationError();
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
//!\note Throws TFontCreationError if the font could not be created, and
|
|
||||||
//! leaves the old font as current.
|
|
||||||
void TFontManager::setTypeface(const std::wstring typeface) {
|
|
||||||
QLocalSocket socket;
|
|
||||||
tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1,
|
|
||||||
t32bitsrv::srvCmdline());
|
|
||||||
|
|
||||||
tipc::Stream stream(&socket);
|
|
||||||
tipc::Message msg;
|
|
||||||
|
|
||||||
stream << (msg << QString("$FNTsetTypeface") << typeface);
|
|
||||||
if (tipc::readMessage(stream, msg) != "ok") throw TFontCreationError();
|
|
||||||
|
|
||||||
// Also, store the font's ascender and descender
|
|
||||||
msg >> m_pimpl->m_ascender >> m_pimpl->m_descender;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
std::wstring TFontManager::getCurrentFamily() const {
|
|
||||||
QLocalSocket socket;
|
|
||||||
tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1,
|
|
||||||
t32bitsrv::srvCmdline());
|
|
||||||
|
|
||||||
tipc::Stream stream(&socket);
|
|
||||||
tipc::Message msg;
|
|
||||||
|
|
||||||
stream << (msg << QString("$FNTgetCurrentFamily"));
|
|
||||||
if (tipc::readMessage(stream, msg) != "ok")
|
|
||||||
throw TException("Could not get font family");
|
|
||||||
|
|
||||||
std::wstring family;
|
|
||||||
msg >> family;
|
|
||||||
return family;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
std::wstring TFontManager::getCurrentTypeface() const {
|
|
||||||
QLocalSocket socket;
|
|
||||||
tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1,
|
|
||||||
t32bitsrv::srvCmdline());
|
|
||||||
|
|
||||||
tipc::Stream stream(&socket);
|
|
||||||
tipc::Message msg;
|
|
||||||
|
|
||||||
stream << (msg << QString("$FNTgetCurrentTypeface"));
|
|
||||||
if (tipc::readMessage(stream, msg) != "ok")
|
|
||||||
throw TException("Could not get font typeface");
|
|
||||||
|
|
||||||
std::wstring typeface;
|
|
||||||
msg >> typeface;
|
|
||||||
return typeface;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::getAllFamilies(std::vector<std::wstring> &families) const {
|
|
||||||
QLocalSocket socket;
|
|
||||||
tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1,
|
|
||||||
t32bitsrv::srvCmdline());
|
|
||||||
|
|
||||||
tipc::Stream stream(&socket);
|
|
||||||
tipc::Message msg;
|
|
||||||
|
|
||||||
stream << (msg << QString("$FNTgetAllFamilies"));
|
|
||||||
if (tipc::readMessage(stream, msg) != "ok")
|
|
||||||
throw TException("Could not get font families");
|
|
||||||
|
|
||||||
msg >> families;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::getAllTypefaces(std::vector<std::wstring> &typefaces) const {
|
|
||||||
QLocalSocket socket;
|
|
||||||
tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1,
|
|
||||||
t32bitsrv::srvCmdline());
|
|
||||||
|
|
||||||
tipc::Stream stream(&socket);
|
|
||||||
tipc::Message msg;
|
|
||||||
|
|
||||||
stream << (msg << QString("$FNTgetAllTypefaces"));
|
|
||||||
if (tipc::readMessage(stream, msg) != "ok")
|
|
||||||
throw TException("Could not get font typefaces");
|
|
||||||
|
|
||||||
msg >> typefaces;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::setVertical(bool vertical) {}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
void TFontManager::setSize(int size) {
|
|
||||||
QLocalSocket socket;
|
|
||||||
tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1,
|
|
||||||
t32bitsrv::srvCmdline());
|
|
||||||
|
|
||||||
tipc::Stream stream(&socket);
|
|
||||||
tipc::Message msg;
|
|
||||||
|
|
||||||
stream << (msg << QString("$FNTsetSize") << size);
|
|
||||||
if (tipc::readMessage(stream, msg) != "ok")
|
|
||||||
throw TException("Unexpected error");
|
|
||||||
|
|
||||||
// Also, update ascender and descender
|
|
||||||
msg >> m_pimpl->m_ascender >> m_pimpl->m_descender;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
TPoint TFontManager::getDistance(wchar_t firstChar, wchar_t secondChar) {
|
|
||||||
QLocalSocket socket;
|
|
||||||
tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1,
|
|
||||||
t32bitsrv::srvCmdline());
|
|
||||||
|
|
||||||
tipc::Stream stream(&socket);
|
|
||||||
tipc::Message msg;
|
|
||||||
|
|
||||||
stream << (msg << QString("$FNTgetDistance") << firstChar << secondChar);
|
|
||||||
if (tipc::readMessage(stream, msg) != "ok")
|
|
||||||
throw TException("Unexpected error");
|
|
||||||
|
|
||||||
TPoint d;
|
|
||||||
msg >> d.x >> d.y;
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
int TFontManager::getMaxHeight() {
|
|
||||||
return m_pimpl->m_ascender - m_pimpl->m_descender;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
int TFontManager::getMaxWidth() {
|
|
||||||
assert(!"not implemented yet");
|
|
||||||
return 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
bool TFontManager::hasVertical() { return false; }
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
bool TFontManager::hasKerning() { return true; }
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
int TFontManager::getLineAscender() { return m_pimpl->m_ascender; }
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
int TFontManager::getLineDescender() { return m_pimpl->m_descender; }
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
TPoint TFontManager::drawChar(TVectorImageP &outImage, wchar_t charcode,
|
|
||||||
wchar_t nextCode) {
|
|
||||||
QLocalSocket socket;
|
|
||||||
tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1,
|
|
||||||
t32bitsrv::srvCmdline());
|
|
||||||
|
|
||||||
tipc::Stream stream(&socket);
|
|
||||||
tipc::Message msg;
|
|
||||||
|
|
||||||
stream << (msg << QString("$FNTdrawCharVI") << charcode << nextCode);
|
|
||||||
if (tipc::readMessage(stream, msg) != "ok")
|
|
||||||
throw TException("Unexpected error");
|
|
||||||
|
|
||||||
TPoint ret;
|
|
||||||
msg >> ret.x >> ret.y;
|
|
||||||
::readVImage(outImage, msg);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
TPoint TFontManager::drawChar(TRasterGR8P &outImage, TPoint &glyphOrigin,
|
|
||||||
wchar_t charcode, wchar_t nextCode) {
|
|
||||||
QLocalSocket socket;
|
|
||||||
tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1,
|
|
||||||
t32bitsrv::srvCmdline());
|
|
||||||
|
|
||||||
tipc::Stream stream(&socket);
|
|
||||||
tipc::Message msg;
|
|
||||||
|
|
||||||
QString shMemId(tipc::uniqueId()), res;
|
|
||||||
{
|
|
||||||
// Invoke the appropriate command
|
|
||||||
stream << (msg << QString("$FNTdrawCharGR") << shMemId << charcode
|
|
||||||
<< nextCode);
|
|
||||||
if (tipc::readMessage(stream, msg) != "ok")
|
|
||||||
throw TException("Unexpected error");
|
|
||||||
}
|
|
||||||
|
|
||||||
TDimension dim(0, 0);
|
|
||||||
msg >> dim.lx >> dim.ly;
|
|
||||||
TPoint ret;
|
|
||||||
msg >> ret.x >> ret.y;
|
|
||||||
|
|
||||||
// Create outImage
|
|
||||||
outImage = TRasterGR8P(dim.lx, dim.ly);
|
|
||||||
|
|
||||||
QSharedMemory shmem(shMemId);
|
|
||||||
shmem.attach();
|
|
||||||
shmem.lock();
|
|
||||||
|
|
||||||
// Copy the returned image to outImage
|
|
||||||
TRasterGR8P ras(dim.lx, dim.ly, dim.lx, (TPixelGR8 *)shmem.data());
|
|
||||||
TRop::copy(outImage, ras);
|
|
||||||
|
|
||||||
shmem.unlock();
|
|
||||||
shmem.detach();
|
|
||||||
|
|
||||||
// Release the shared segment
|
|
||||||
stream << (msg << tipc::clr << QString("$shmem_release") << shMemId);
|
|
||||||
if (tipc::readMessage(stream, msg) != "ok")
|
|
||||||
throw TException("Unexpected error");
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
TPoint TFontManager::drawChar(TRasterCM32P &outImage, TPoint &glyphOrigin,
|
|
||||||
int inkId, wchar_t charcode, wchar_t nextCode) {
|
|
||||||
QLocalSocket socket;
|
|
||||||
tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1,
|
|
||||||
t32bitsrv::srvCmdline());
|
|
||||||
|
|
||||||
tipc::Stream stream(&socket);
|
|
||||||
tipc::Message msg;
|
|
||||||
|
|
||||||
QString shMemId(tipc::uniqueId()), res;
|
|
||||||
{
|
|
||||||
// Invoke the appropriate command
|
|
||||||
stream << (msg << QString("$FNTdrawCharCM") << inkId << shMemId << charcode
|
|
||||||
<< nextCode);
|
|
||||||
if (tipc::readMessage(stream, msg) != "ok")
|
|
||||||
throw TException("Unexpected error");
|
|
||||||
}
|
|
||||||
|
|
||||||
TDimension dim(0, 0);
|
|
||||||
msg >> dim.lx >> dim.ly;
|
|
||||||
TPoint ret;
|
|
||||||
msg >> ret.x >> ret.y;
|
|
||||||
|
|
||||||
// Create outImage
|
|
||||||
outImage = TRasterCM32P(dim.lx, dim.ly);
|
|
||||||
|
|
||||||
QSharedMemory shmem(shMemId);
|
|
||||||
shmem.attach();
|
|
||||||
shmem.lock();
|
|
||||||
|
|
||||||
// Copy the returned image to outImage
|
|
||||||
TRasterCM32P ras(dim.lx, dim.ly, dim.lx, (TPixelCM32 *)shmem.data());
|
|
||||||
TRop::copy(outImage, ras);
|
|
||||||
|
|
||||||
shmem.unlock();
|
|
||||||
shmem.detach();
|
|
||||||
|
|
||||||
// Release the shared segment
|
|
||||||
stream << (msg << tipc::clr << QString("$shmem_release") << shMemId);
|
|
||||||
if (tipc::readMessage(stream, msg) != "ok")
|
|
||||||
throw TException("Unexpected error");
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <QFontMetrics>
|
#include <QFontMetrics>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QPainterPath>
|
#include <QPainterPath>
|
||||||
|
#include <QPainter>
|
||||||
#include <QRawFont>
|
#include <QRawFont>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -58,7 +59,8 @@ TFont::~TFont() { delete m_pimpl; }
|
||||||
|
|
||||||
TFont::Impl::Impl(const QString &family, const QString &style, int size) {
|
TFont::Impl::Impl(const QString &family, const QString &style, int size) {
|
||||||
m_font = QFont(family, size);
|
m_font = QFont(family, size);
|
||||||
m_font.setStyleName(style);
|
m_font.setBold(TFontManager::instance()->isBold(family, style));
|
||||||
|
m_font.setItalic(TFontManager::instance()->isItalic(family, style));
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -153,7 +155,7 @@ TPoint TFont::drawChar(TVectorImageP &image, wchar_t charcode,
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
TPoint TFont::drawChar(TRasterGR8P &outImage, TPoint &unused, wchar_t charcode,
|
TPoint TFont::drawChar(QImage &outImage, TPoint &unused, wchar_t charcode,
|
||||||
wchar_t nextCharCode) const {
|
wchar_t nextCharCode) const {
|
||||||
QRawFont raw(QRawFont::fromFont(m_pimpl->m_font));
|
QRawFont raw(QRawFont::fromFont(m_pimpl->m_font));
|
||||||
|
|
||||||
|
@ -165,24 +167,18 @@ TPoint TFont::drawChar(TRasterGR8P &outImage, TPoint &unused, wchar_t charcode,
|
||||||
return TPoint(0, 0);
|
return TPoint(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage image(raw.alphaMapForGlyph(indices[0], QRawFont::PixelAntialiasing));
|
QImage image = raw.alphaMapForGlyph(indices[0], QRawFont::PixelAntialiasing);
|
||||||
|
if (image.format() != QImage::Format_Indexed8 &&
|
||||||
if (image.format() != QImage::Format_Indexed8)
|
image.format() != QImage::Format_Alpha8)
|
||||||
throw TException(L"bad QImage format " + image.format());
|
throw TException(L"bad QImage format " + image.format());
|
||||||
|
|
||||||
int height = image.height();
|
QRectF boundingRect = raw.boundingRect(indices[0]);
|
||||||
int width = image.width();
|
|
||||||
|
|
||||||
outImage = TRasterGR8P(width, height);
|
outImage = QImage(image.width(), raw.ascent() + raw.descent(),
|
||||||
|
QImage::Format_Grayscale8);
|
||||||
#if 0
|
outImage.fill(255);
|
||||||
TPixelGR8 bgp;
|
QPainter painter(&outImage);
|
||||||
bgp.value = 255;
|
painter.drawImage(0, boundingRect.top() + raw.ascent(), image);
|
||||||
outImage->fill(bgp);
|
|
||||||
#endif
|
|
||||||
void *data = outImage->getRawData();
|
|
||||||
|
|
||||||
memcpy(data, image.bits(), image.byteCount());
|
|
||||||
|
|
||||||
return getDistance(charcode, nextCharCode);
|
return getDistance(charcode, nextCharCode);
|
||||||
}
|
}
|
||||||
|
@ -191,24 +187,24 @@ TPoint TFont::drawChar(TRasterGR8P &outImage, TPoint &unused, wchar_t charcode,
|
||||||
|
|
||||||
TPoint TFont::drawChar(TRasterCM32P &outImage, TPoint &unused, int inkId,
|
TPoint TFont::drawChar(TRasterCM32P &outImage, TPoint &unused, int inkId,
|
||||||
wchar_t charcode, wchar_t nextCharCode) const {
|
wchar_t charcode, wchar_t nextCharCode) const {
|
||||||
TRasterGR8P grayAppImage;
|
QImage grayAppImage;
|
||||||
this->drawChar(grayAppImage, unused, charcode, nextCharCode);
|
this->drawChar(grayAppImage, unused, charcode, nextCharCode);
|
||||||
|
|
||||||
int lx = grayAppImage->getLx();
|
int lx = grayAppImage.width();
|
||||||
int ly = grayAppImage->getLy();
|
int ly = grayAppImage.height();
|
||||||
|
|
||||||
outImage = TRasterCM32P(lx, ly);
|
outImage = TRasterCM32P(lx, ly);
|
||||||
|
outImage->lock();
|
||||||
|
|
||||||
assert(TPixelCM32::getMaxTone() == 255);
|
assert(TPixelCM32::getMaxTone() == 255);
|
||||||
TPixelCM32 bgColor(0, 0, TPixelCM32::getMaxTone());
|
TPixelCM32 bgColor(0, 0, TPixelCM32::getMaxTone());
|
||||||
grayAppImage->lock();
|
|
||||||
outImage->lock();
|
|
||||||
int ty = 0;
|
int ty = 0;
|
||||||
|
|
||||||
for (int gy = ly - 1; gy >= 0; --gy, ++ty) {
|
for (int gy = ly - 1; gy >= 0; --gy, ++ty) {
|
||||||
TPixelGR8 *srcPix = grayAppImage->pixels(gy);
|
uchar *srcPix = grayAppImage.scanLine(gy);
|
||||||
TPixelCM32 *tarPix = outImage->pixels(ty);
|
TPixelCM32 *tarPix = outImage->pixels(ty);
|
||||||
for (int x = 0; x < lx; ++x) {
|
for (int x = 0; x < lx; ++x) {
|
||||||
int tone = srcPix->value;
|
int tone = (int)(*srcPix);
|
||||||
|
|
||||||
if (tone == 255)
|
if (tone == 255)
|
||||||
*tarPix = bgColor;
|
*tarPix = bgColor;
|
||||||
|
@ -219,7 +215,6 @@ TPoint TFont::drawChar(TRasterCM32P &outImage, TPoint &unused, int inkId,
|
||||||
++tarPix;
|
++tarPix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
grayAppImage->unlock();
|
|
||||||
outImage->unlock();
|
outImage->unlock();
|
||||||
|
|
||||||
return getDistance(charcode, nextCharCode);
|
return getDistance(charcode, nextCharCode);
|
||||||
|
@ -462,3 +457,13 @@ void TFontManager::getAllTypefaces(vector<wstring> &typefaces) const {
|
||||||
void TFontManager::setVertical(bool vertical) {}
|
void TFontManager::setVertical(bool vertical) {}
|
||||||
|
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
|
|
||||||
|
bool TFontManager::isBold(const QString &family, const QString &style) {
|
||||||
|
return m_pimpl->m_qfontdb->bold(family, style);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
|
||||||
|
bool TFontManager::isItalic(const QString &family, const QString &style) {
|
||||||
|
return m_pimpl->m_qfontdb->italic(family, style);
|
||||||
|
}
|
|
@ -26,18 +26,6 @@
|
||||||
class TVectorImageP;
|
class TVectorImageP;
|
||||||
class TFont;
|
class TFont;
|
||||||
|
|
||||||
//-----------------------------------------------------
|
|
||||||
|
|
||||||
// TFont declaration. The class is currently not directly available under 64-bit
|
|
||||||
// MAC OSX.
|
|
||||||
|
|
||||||
#if !defined(__LP64__) || !defined(MACOSX)
|
|
||||||
|
|
||||||
#ifdef MACOSX
|
|
||||||
#include <ApplicationServices/ApplicationServices.h>
|
|
||||||
#include <Carbon/Carbon.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//=================================================================================================
|
//=================================================================================================
|
||||||
|
|
||||||
//! Class to manage loading and rendering of fonts.
|
//! Class to manage loading and rendering of fonts.
|
||||||
|
@ -50,20 +38,14 @@ private:
|
||||||
friend class TFontManager;
|
friend class TFontManager;
|
||||||
Impl *m_pimpl;
|
Impl *m_pimpl;
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
TFont(const LOGFONTW &, HDC hdc);
|
|
||||||
#elif defined(MACOSX)
|
|
||||||
TFont(ATSUFontID, int size);
|
|
||||||
#else
|
|
||||||
TFont(const std::wstring family, const std::wstring face, int size);
|
TFont(const std::wstring family, const std::wstring face, int size);
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~TFont();
|
~TFont();
|
||||||
|
|
||||||
TPoint drawChar(TVectorImageP &outImage, wchar_t charcode,
|
TPoint drawChar(TVectorImageP &outImage, wchar_t charcode,
|
||||||
wchar_t nextCode = 0) const;
|
wchar_t nextCode = 0) const;
|
||||||
TPoint drawChar(TRasterGR8P &outImage, TPoint &glyphOrigin, wchar_t charcode,
|
TPoint drawChar(QImage &outImage, TPoint &glyphOrigin, wchar_t charcode,
|
||||||
wchar_t nextCode = 0) const;
|
wchar_t nextCode = 0) const;
|
||||||
TPoint drawChar(TRasterCM32P &outImage, TPoint &glyphOrigin, int inkId,
|
TPoint drawChar(TRasterCM32P &outImage, TPoint &glyphOrigin, int inkId,
|
||||||
wchar_t charcode, wchar_t nextCode = 0) const;
|
wchar_t charcode, wchar_t nextCode = 0) const;
|
||||||
|
@ -89,8 +71,6 @@ private:
|
||||||
TFont &operator=(const TFont &);
|
TFont &operator=(const TFont &);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__LP64__ || !MACOSX
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
class TFontCreationError final : public TException {
|
class TFontCreationError final : public TException {
|
||||||
|
@ -138,16 +118,17 @@ public:
|
||||||
void setVertical(bool vertical);
|
void setVertical(bool vertical);
|
||||||
void setSize(int size);
|
void setSize(int size);
|
||||||
|
|
||||||
// --------- TFont methods called on curren font -----------
|
bool isBold(const QString &family, const QString &style);
|
||||||
|
bool isItalic(const QString &family, const QString &style);
|
||||||
|
|
||||||
#if !defined(__LP64__) || defined(LINUX)
|
// --------- TFont methods called on curren font -----------
|
||||||
|
|
||||||
TPoint drawChar(TVectorImageP &outImage, wchar_t charcode,
|
TPoint drawChar(TVectorImageP &outImage, wchar_t charcode,
|
||||||
wchar_t nextCode = 0) {
|
wchar_t nextCode = 0) {
|
||||||
return getCurrentFont()->drawChar(outImage, charcode, nextCode);
|
return getCurrentFont()->drawChar(outImage, charcode, nextCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
TPoint drawChar(TRasterGR8P &outImage, TPoint &glyphOrigin, wchar_t charcode,
|
TPoint drawChar(QImage &outImage, TPoint &glyphOrigin, wchar_t charcode,
|
||||||
wchar_t nextCode = 0) {
|
wchar_t nextCode = 0) {
|
||||||
return getCurrentFont()->drawChar(outImage, glyphOrigin, charcode,
|
return getCurrentFont()->drawChar(outImage, glyphOrigin, charcode,
|
||||||
nextCode);
|
nextCode);
|
||||||
|
@ -169,26 +150,6 @@ public:
|
||||||
int getLineAscender() { return getCurrentFont()->getLineAscender(); }
|
int getLineAscender() { return getCurrentFont()->getLineAscender(); }
|
||||||
int getLineDescender() { return getCurrentFont()->getLineDescender(); }
|
int getLineDescender() { return getCurrentFont()->getLineDescender(); }
|
||||||
bool hasVertical() { return getCurrentFont()->hasVertical(); }
|
bool hasVertical() { return getCurrentFont()->hasVertical(); }
|
||||||
|
|
||||||
#else //__LP64__
|
|
||||||
|
|
||||||
TPoint drawChar(TVectorImageP &outImage, wchar_t charcode,
|
|
||||||
wchar_t nextCode = 0);
|
|
||||||
TPoint drawChar(TRasterGR8P &outImage, TPoint &glyphOrigin, wchar_t charcode,
|
|
||||||
wchar_t nextCode = 0);
|
|
||||||
TPoint drawChar(TRasterCM32P &outImage, TPoint &glyphOrigin, int inkId,
|
|
||||||
wchar_t charcode, wchar_t nextCode = 0);
|
|
||||||
|
|
||||||
TPoint getDistance(wchar_t firstChar, wchar_t secondChar);
|
|
||||||
|
|
||||||
int getMaxHeight();
|
|
||||||
int getMaxWidth();
|
|
||||||
bool hasKerning();
|
|
||||||
int getLineAscender();
|
|
||||||
int getLineDescender();
|
|
||||||
bool hasVertical();
|
|
||||||
|
|
||||||
#endif //__LP64__
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
|
@ -181,7 +181,6 @@ set(SOURCES
|
||||||
../common/tvrender/tcolorstyles.cpp
|
../common/tvrender/tcolorstyles.cpp
|
||||||
../common/tvrender/tellipticbrush.cpp
|
../common/tvrender/tellipticbrush.cpp
|
||||||
../common/tvrender/tflash.cpp
|
../common/tvrender/tflash.cpp
|
||||||
../common/tvrender/tfont_proxy.cpp
|
|
||||||
../common/tvrender/qtofflinegl.cpp
|
../common/tvrender/qtofflinegl.cpp
|
||||||
../common/tvrender/tglcurves.cpp
|
../common/tvrender/tglcurves.cpp
|
||||||
../common/tvrender/tglregions.cpp
|
../common/tvrender/tglregions.cpp
|
||||||
|
@ -244,22 +243,18 @@ set(SOURCES
|
||||||
../common/tapptools/tenv.cpp
|
../common/tapptools/tenv.cpp
|
||||||
../common/tmeshimage/tmeshimage.cpp
|
../common/tmeshimage/tmeshimage.cpp
|
||||||
../common/tmsgcore.cpp
|
../common/tmsgcore.cpp
|
||||||
|
../common/tvrender/tfont_qt.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if(BUILD_TARGET_WIN)
|
if(BUILD_TARGET_WIN)
|
||||||
set(SOURCES ${SOURCES}
|
set(SOURCES ${SOURCES}
|
||||||
../common/tsound/tsound_nt.cpp
|
../common/tsound/tsound_nt.cpp
|
||||||
../common/tvrender/tfont_nt.cpp
|
|
||||||
)
|
)
|
||||||
elseif(BUILD_TARGET_APPLE)
|
elseif(BUILD_TARGET_APPLE)
|
||||||
set(SOURCES ${SOURCES}
|
set(SOURCES ${SOURCES}
|
||||||
../common/tsound/tsound_mac.cpp
|
../common/tsound/tsound_mac.cpp
|
||||||
../common/tvrender/tfont_mac.cpp
|
|
||||||
)
|
)
|
||||||
elseif(BUILD_TARGET_UNIX)
|
elseif(BUILD_TARGET_UNIX)
|
||||||
set(SOURCES ${SOURCES}
|
|
||||||
../common/tvrender/tfont_qt.cpp
|
|
||||||
)
|
|
||||||
if(SDL_LIB_FOUND)
|
if(SDL_LIB_FOUND)
|
||||||
set(SOURCES ${SOURCES}
|
set(SOURCES ${SOURCES}
|
||||||
../common/tsound/tsound_sdl.cpp
|
../common/tsound/tsound_sdl.cpp
|
||||||
|
|
|
@ -407,7 +407,7 @@ TypeTool::TypeTool()
|
||||||
, m_textBox(TRectD(0, 0, 0, 0))
|
, m_textBox(TRectD(0, 0, 0, 0))
|
||||||
, m_cursorPoint(TPointD(0, 0))
|
, m_cursorPoint(TPointD(0, 0))
|
||||||
, m_startPoint(TPointD(0, 0))
|
, m_startPoint(TPointD(0, 0))
|
||||||
, m_dimension(70)
|
, m_dimension(1) // to be set the m_size value on the first-click
|
||||||
, m_validFonts(true) // false)
|
, m_validFonts(true) // false)
|
||||||
, m_fontYOffset(0)
|
, m_fontYOffset(0)
|
||||||
, m_cursorId(ToolCursor::CURSOR_NO)
|
, m_cursorId(ToolCursor::CURSOR_NO)
|
||||||
|
@ -423,11 +423,12 @@ TypeTool::TypeTool()
|
||||||
, m_undo(0) {
|
, m_undo(0) {
|
||||||
bind(TTool::CommonLevels | TTool::EmptyTarget);
|
bind(TTool::CommonLevels | TTool::EmptyTarget);
|
||||||
m_prop.bind(m_fontFamilyMenu);
|
m_prop.bind(m_fontFamilyMenu);
|
||||||
// Su mac non e' visibile il menu dello style perche' e' stato inserito nel nome
|
// Su mac non e' visibile il menu dello style perche' e' stato inserito nel
|
||||||
// della font.
|
// nome
|
||||||
#ifndef MACOSX
|
// della font.
|
||||||
|
//#ifndef MACOSX
|
||||||
m_prop.bind(m_typeFaceMenu);
|
m_prop.bind(m_typeFaceMenu);
|
||||||
#endif
|
//#endif
|
||||||
m_prop.bind(m_size);
|
m_prop.bind(m_size);
|
||||||
m_prop.bind(m_vertical);
|
m_prop.bind(m_vertical);
|
||||||
m_vertical.setId("Orientation");
|
m_vertical.setId("Orientation");
|
||||||
|
@ -601,7 +602,7 @@ void TypeTool::setSize(std::wstring strSize) {
|
||||||
|
|
||||||
TImageP img = getImage(true);
|
TImageP img = getImage(true);
|
||||||
TToonzImageP ti = img;
|
TToonzImageP ti = img;
|
||||||
if (ti) TFontManager::instance()->setSize((int)dimension);
|
TFontManager::instance()->setSize((int)dimension);
|
||||||
|
|
||||||
assert(m_dimension != 0);
|
assert(m_dimension != 0);
|
||||||
double ratio = dimension / m_dimension;
|
double ratio = dimension / m_dimension;
|
||||||
|
@ -869,7 +870,7 @@ glPushMatrix();
|
||||||
|
|
||||||
double charWidth = 0;
|
double charWidth = 0;
|
||||||
if (TVectorImageP vi = m_string[j].m_char) {
|
if (TVectorImageP vi = m_string[j].m_char) {
|
||||||
TTranslation transl(m_string[j].m_charPosition);
|
TTranslation transl(convert(descenderP) + m_string[j].m_charPosition);
|
||||||
const TVectorRenderData rd(transl, TRect(), vPalette, 0, false);
|
const TVectorRenderData rd(transl, TRect(), vPalette, 0, false);
|
||||||
tglDraw(rd, vi.getPointer());
|
tglDraw(rd, vi.getPointer());
|
||||||
charWidth = vi->getBBox().getLx();
|
charWidth = vi->getBBox().getLx();
|
||||||
|
@ -878,7 +879,7 @@ glPushMatrix();
|
||||||
ti->setPalette(vPalette);
|
ti->setPalette(vPalette);
|
||||||
|
|
||||||
TPoint rasterCenter(dim.lx / 2, dim.ly / 2);
|
TPoint rasterCenter(dim.lx / 2, dim.ly / 2);
|
||||||
TTranslation transl1(convert(descenderP + rasterCenter));
|
TTranslation transl1(convert(rasterCenter));
|
||||||
TTranslation transl2(m_string[j].m_charPosition);
|
TTranslation transl2(m_string[j].m_charPosition);
|
||||||
GLRasterPainter::drawRaster(transl2 * m_scale * transl1, ti, false);
|
GLRasterPainter::drawRaster(transl2 * m_scale * transl1, ti, false);
|
||||||
|
|
||||||
|
@ -971,16 +972,17 @@ void TypeTool::addTextToToonzImage(const TToonzImageP ¤tImage) {
|
||||||
TRasterCM32P targetRaster = currentImage->getRaster();
|
TRasterCM32P targetRaster = currentImage->getRaster();
|
||||||
TRect changedArea;
|
TRect changedArea;
|
||||||
|
|
||||||
TPoint descenderP(0, TFontManager::instance()->getLineDescender());
|
|
||||||
|
|
||||||
UINT j;
|
UINT j;
|
||||||
for (j = 0; j < size; j++) {
|
for (j = 0; j < size; j++) {
|
||||||
if (m_string[j].isReturn()) continue;
|
if (m_string[j].isReturn()) continue;
|
||||||
|
|
||||||
if (TToonzImageP ti = m_string[j].m_char) {
|
if (TToonzImageP ti = m_string[j].m_char) {
|
||||||
TRectD srcBBox = ti->getBBox() + m_string[j].m_charPosition;
|
TRectD srcBBox = ti->getBBox() + m_string[j].m_charPosition;
|
||||||
changedArea +=
|
TDimensionD dim = srcBBox.getSize();
|
||||||
ToonzImageUtils::convertWorldToRaster(srcBBox, currentImage);
|
TDimensionD enlargeAmount(dim.lx * (m_scale.a11 - 1.0),
|
||||||
|
dim.ly * (m_scale.a22 - 1.0));
|
||||||
|
changedArea += ToonzImageUtils::convertWorldToRaster(
|
||||||
|
srcBBox.enlarge(enlargeAmount), currentImage);
|
||||||
/*
|
/*
|
||||||
if( instance->hasVertical() && m_isVertical)
|
if( instance->hasVertical() && m_isVertical)
|
||||||
vi->transform( TRotation(m_startPoint,-90) );
|
vi->transform( TRotation(m_startPoint,-90) );
|
||||||
|
@ -988,8 +990,6 @@ vi->transform( TRotation(m_startPoint,-90) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
changedArea = changedArea + descenderP;
|
|
||||||
|
|
||||||
if (!changedArea.isEmpty()) {
|
if (!changedArea.isEmpty()) {
|
||||||
TTileSetCM32 *beforeTiles = new TTileSetCM32(targetRaster->getSize());
|
TTileSetCM32 *beforeTiles = new TTileSetCM32(targetRaster->getSize());
|
||||||
beforeTiles->add(targetRaster, changedArea);
|
beforeTiles->add(targetRaster, changedArea);
|
||||||
|
@ -999,10 +999,9 @@ vi->transform( TRotation(m_startPoint,-90) );
|
||||||
|
|
||||||
if (TToonzImageP srcTi = m_string[j].m_char) {
|
if (TToonzImageP srcTi = m_string[j].m_char) {
|
||||||
TRasterCM32P srcRaster = srcTi->getRaster();
|
TRasterCM32P srcRaster = srcTi->getRaster();
|
||||||
TTranslation transl1(convert(descenderP));
|
|
||||||
TTranslation transl2(m_string[j].m_charPosition +
|
TTranslation transl2(m_string[j].m_charPosition +
|
||||||
convert(targetRaster->getCenter()));
|
convert(targetRaster->getCenter()));
|
||||||
TRop::over(targetRaster, srcRaster, transl2 * m_scale * transl1);
|
TRop::over(targetRaster, srcRaster, transl2 * m_scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1047,8 +1046,10 @@ void TypeTool::addTextToImage() {
|
||||||
for (j = 0; j < size; j++) {
|
for (j = 0; j < size; j++) {
|
||||||
if (m_string[j].isReturn()) continue;
|
if (m_string[j].isReturn()) continue;
|
||||||
|
|
||||||
|
TPoint descenderP(0, TFontManager::instance()->getLineDescender());
|
||||||
if (TVectorImageP vi = m_string[j].m_char) {
|
if (TVectorImageP vi = m_string[j].m_char) {
|
||||||
vi->transform(TTranslation(m_string[j].m_charPosition));
|
vi->transform(
|
||||||
|
TTranslation(convert(descenderP) + m_string[j].m_charPosition));
|
||||||
if (instance->hasVertical() && m_isVertical)
|
if (instance->hasVertical() && m_isVertical)
|
||||||
vi->transform(TRotation(m_startPoint, -90));
|
vi->transform(TRotation(m_startPoint, -90));
|
||||||
images.push_back(vi.getPointer());
|
images.push_back(vi.getPointer());
|
||||||
|
@ -1167,10 +1168,10 @@ void TypeTool::leftButtonDown(const TPointD &pos, const TMouseEvent &) {
|
||||||
TVectorImageP vi = img;
|
TVectorImageP vi = img;
|
||||||
TToonzImageP ti = img;
|
TToonzImageP ti = img;
|
||||||
|
|
||||||
if (vi) setSize(m_size.getValue());
|
|
||||||
|
|
||||||
if (!vi && !ti) return;
|
if (!vi && !ti) return;
|
||||||
|
|
||||||
|
setSize(m_size.getValue());
|
||||||
|
|
||||||
if (m_isFrameCreated) {
|
if (m_isFrameCreated) {
|
||||||
if (vi)
|
if (vi)
|
||||||
m_undo = new UndoTypeTool(
|
m_undo = new UndoTypeTool(
|
||||||
|
|
Loading…
Reference in a new issue