2 * Copyright 2008-2009, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * François Revol <revol@free.fr>
9 #include "StyledTextImporter.h"
16 #include <Archivable.h>
17 #include <ByteOrder.h>
31 #include "PathContainer.h"
34 #include "StyleContainer.h"
35 #include "VectorPath.h"
38 #undef B_TRANSLATION_CONTEXT
39 #define B_TRANSLATION_CONTEXT "Icon-O-Matic-StyledTextImport"
40 //#define CALLED() printf("%s()\n", __FUNCTION__);
41 #define CALLED() do {} while (0)
46 class ShapeIterator
: public BShapeIterator
{
48 ShapeIterator(Icon
*icon
, Shape
*to
, BPoint offset
, const char *name
);
51 virtual status_t
IterateMoveTo(BPoint
*point
);
52 virtual status_t
IterateLineTo(int32 lineCount
, BPoint
*linePts
);
53 virtual status_t
IterateBezierTo(int32 bezierCount
, BPoint
*bezierPts
);
54 virtual status_t
IterateClose();
57 VectorPath
*CurrentPath();
69 ShapeIterator::ShapeIterator(Icon
*icon
, Shape
*to
, BPoint offset
,
79 fHasLastPoint
= false;
83 ShapeIterator::IterateMoveTo(BPoint
*point
)
90 //fPath->AddPoint(fOffset + *point);
91 fLastPoint
= fOffset
+ *point
;
97 ShapeIterator::IterateLineTo(int32 lineCount
, BPoint
*linePts
)
102 while (lineCount
--) {
103 fPath
->AddPoint(fOffset
+ *linePts
);
104 fLastPoint
= fOffset
+ *linePts
;
105 fHasLastPoint
= true;
112 ShapeIterator::IterateBezierTo(int32 bezierCount
, BPoint
*bezierPts
)
117 BPoint
start(bezierPts
[0]);
120 while (bezierCount
--) {
121 fPath
->AddPoint(fOffset
+ bezierPts
[0],
122 fLastPoint
, fOffset
+ bezierPts
[1], true);
123 fLastPoint
= fOffset
+ bezierPts
[2];
126 fPath
->AddPoint(fLastPoint
);
127 fHasLastPoint
= true;
132 ShapeIterator::IterateClose()
137 fPath
->SetClosed(true);
139 fHasLastPoint
= false;
144 ShapeIterator::CurrentPath()
149 fPath
= new (nothrow
) VectorPath();
150 fPath
->SetName(fName
);
155 ShapeIterator::NextPath()
159 fIcon
->Paths()->AddPath(fPath
);
160 fShape
->Paths()->AddPath(fPath
);
169 StyledTextImporter::StyledTextImporter()
178 StyledTextImporter::~StyledTextImporter()
185 StyledTextImporter::Import(Icon
* icon
, BMessage
* clipping
)
191 if (clipping
== NULL
)
193 if (clipping
->FindData("text/plain",
194 B_MIME_TYPE
, (const void **)&text
, &textLength
) == B_OK
) {
195 text_run_array
*runs
= NULL
;
197 if (clipping
->FindData("application/x-vnd.Be-text_run_array",
198 B_MIME_TYPE
, (const void **)&runs
, &runsLength
) < B_OK
)
200 BString
str(text
, textLength
);
201 return _Import(icon
, str
.String(), runs
);
208 StyledTextImporter::Import(Icon
* icon
, const entry_ref
* ref
)
212 BFile
file(ref
, B_READ_ONLY
);
213 err
= file
.InitCheck();
217 BNodeInfo
info(&file
);
218 char mime
[B_MIME_TYPE_LENGTH
];
219 err
= info
.GetType(mime
);
223 if (strncmp(mime
, "text/plain", B_MIME_TYPE_LENGTH
))
227 err
= file
.GetSize(&size
);
230 if (size
> 1 * 1024 * 1024) // Don't load files that big
234 mio
.SetSize((size_t)size
+ 1);
235 memset((void *)mio
.Buffer(), 0, (size_t)size
+ 1);
237 // TODO: read runs from attribute
239 return _Import(icon
, (const char *)mio
.Buffer(), NULL
);
245 StyledTextImporter::_Import(Icon
* icon
, const char *text
, text_run_array
*runs
)
248 status_t ret
= Init(icon
);
250 printf("StyledTextImporter::Import() - Init() error: %s\n",
256 if (str
.Length() > 50) {
257 BAlert
* alert
= new BAlert(B_TRANSLATE("Text too long"),
258 B_TRANSLATE("The text you are trying to import is quite long, "
260 B_TRANSLATE("Yes"), B_TRANSLATE("No"), NULL
,
261 B_WIDTH_AS_USUAL
, B_WARNING_ALERT
);
266 // import run colors as styles
269 fStyleMap
= new struct style_map
[runs
->count
];
270 for (int32 i
= 0; runs
&& i
< runs
->count
; i
++) {
271 _AddStyle(icon
, &runs
->runs
[i
]);
275 int32 currentRun
= 0;
276 text_run
*run
= NULL
;
278 run
= &runs
->runs
[0];
279 int32 len
= str
.Length();
280 int32 chars
= str
.CountChars();
282 BPoint
offset(origin
);
284 for (int32 i
= 0, c
= 0; i
< len
&& c
< chars
; c
++) {
285 // make sure we are still on the (good) run
286 while (run
&& currentRun
< runs
->count
- 1 &&
287 i
>= runs
->runs
[currentRun
+ 1].offset
) {
288 run
= &runs
->runs
[++currentRun
];
289 //printf("switching to run %d\n", currentRun);
293 for (charLen
= 1; str
.ByteAt(i
+ charLen
) & 0x80; charLen
++);
296 BShape
*glyphs
[1] = { &glyph
};
297 BFont
font(be_plain_font
);
302 if (offset
== BPoint(0,0)) {
304 font
.GetHeight(&height
);
305 origin
.y
+= height
.ascent
;
309 if (str
[i
] == '\n') {
310 // XXX: should take the MAX() for the line
311 // XXX: should use descent + leading from previous line
313 font
.GetHeight(&height
);
314 origin
.y
+= height
.ascent
+ height
.descent
+ height
.leading
;
321 charWidth
= font
.StringWidth(str
.String() + i
, charLen
);
322 //printf("StringWidth( %d) = %f\n", charLen, charWidth);
323 BString
glyphName(str
.String() + i
, charLen
);
324 glyphName
.Prepend("Glyph (");
325 glyphName
.Append(")");
327 font
.GetGlyphShapes((str
.String() + i
), 1, glyphs
);
328 if (glyph
.Bounds().IsValid()) {
329 //offset.x += glyph.Bounds().Width();
330 offset
.x
+= charWidth
;
331 Shape
* shape
= new (nothrow
) Shape(NULL
);
334 shape
->SetName(glyphName
.String());
335 if (!icon
->Shapes()->AddShape(shape
)) {
339 for (int j
= 0; run
&& j
< fStyleCount
; j
++) {
340 if (fStyleMap
[j
].run
== run
) {
341 shape
->SetStyle(fStyleMap
[j
].style
);
345 ShapeIterator
iterator(icon
, shape
, offset
, glyphName
.String());
346 if (iterator
.Iterate(&glyph
) < B_OK
)
351 // skip the rest of UTF-8 char bytes
352 for (i
++; i
< len
&& str
[i
] & 0x80; i
++);
365 StyledTextImporter::_AddStyle(Icon
*icon
, text_run
*run
)
370 rgb_color color
= run
->color
;
371 Style
* style
= new(std::nothrow
) Style(color
);
375 sprintf(name
, B_TRANSLATE("Color (#%02x%02x%02x)"),
376 color
.red
, color
.green
, color
.blue
);
377 style
->SetName(name
);
380 for (int i
= 0; i
< fStyleCount
; i
++) {
381 if (*style
== *(fStyleMap
[i
].style
)) {
383 style
= fStyleMap
[i
].style
;
389 if (!found
&& !icon
->Styles()->AddStyle(style
)) {
394 fStyleMap
[fStyleCount
].run
= run
;
395 fStyleMap
[fStyleCount
].style
= style
;
403 StyledTextImporter::_AddPaths(Icon
*icon
, BShape
*shape
)
411 StyledTextImporter::_AddShape(Icon
*icon
, BShape
*shape
, text_run
*run
)