Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
246a0dc8
authored
Jan 02, 2017
by
Julian Cable
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
add SSA/ASS specific files from branch
parent
163a3a7b
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
688 additions
and
0 deletions
library/src/main/java/com/google/android/exoplayer2/text/ssa/SSACue.java
library/src/main/java/com/google/android/exoplayer2/text/ssa/SSADecoder.java
library/src/main/java/com/google/android/exoplayer2/text/ssa/SSASubtitle.java
library/src/main/java/com/google/android/exoplayer2/text/ssa/Style.java
library/src/main/java/com/google/android/exoplayer2/text/ssa/SSACue.java
0 → 100644
View file @
246a0dc8
package
com
.
google
.
android
.
exoplayer2
.
text
.
ssa
;
import
com.google.android.exoplayer2.text.Cue
;
/**
* Created by cablej01 on 02/01/2017.
*/
public
class
SSACue
extends
Cue
{
private
Style
style
=
null
;
private
int
layer
;
private
String
effect
;
private
String
richText
=
null
;
public
SSACue
(
String
text
)
{
this
(
text
,
null
,
0
,
null
);
}
public
SSACue
(
String
text
,
Style
style
,
int
layer
,
String
effect
)
{
super
(
text
.
replaceAll
(
"\\{[^{]*\\}"
,
""
));
this
.
richText
=
text
;
this
.
layer
=
layer
;
this
.
effect
=
effect
;
this
.
style
=
style
;
// TODO map SSA fields to superclass fields
}
public
Style
getStyle
()
{
return
style
;
}
public
int
getLayer
()
{
return
layer
;
}
public
String
getEffect
()
{
return
effect
;
}
public
String
getRichText
()
{
return
richText
;
}
}
library/src/main/java/com/google/android/exoplayer2/text/ssa/SSADecoder.java
0 → 100644
View file @
246a0dc8
package
com
.
google
.
android
.
exoplayer2
.
text
.
ssa
;
import
android.content.Intent
;
import
android.text.Layout
;
import
android.util.ArrayMap
;
import
android.util.Log
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.text.Cue
;
import
com.google.android.exoplayer2.text.SimpleSubtitleDecoder
;
import
com.google.android.exoplayer2.util.LongArray
;
import
com.google.android.exoplayer2.util.ParsableBitArray
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
java.io.UnsupportedEncodingException
;
import
java.text.SimpleDateFormat
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
static
android
.
R
.
attr
.
breadCrumbShortTitle
;
import
static
android
.
R
.
attr
.
data
;
import
static
android
.
R
.
attr
.
format
;
import
static
android
.
R
.
attr
.
key
;
import
static
android
.
R
.
attr
.
lines
;
import
static
android
.
R
.
attr
.
subtitle
;
import
static
android
.
R
.
attr
.
text
;
import
static
android
.
R
.
attr
.
textAlignment
;
import
static
android
.
R
.
attr
.
track
;
import
static
android
.
icu
.
lang
.
UCharacter
.
GraphemeClusterBreak
.
L
;
import
static
android
.
webkit
.
ConsoleMessage
.
MessageLevel
.
LOG
;
import
static
com
.
google
.
android
.
exoplayer2
.
text
.
Cue
.
DIMEN_UNSET
;
import
static
com
.
google
.
android
.
exoplayer2
.
text
.
Cue
.
TYPE_UNSET
;
/**
* Created by cablej01 on 26/12/2016.
*/
/* Notes from ojw28
Subtitles are really complicated because they can be packaged in different units of granularity
and with different ways of conveying timing information. Roughly speaking, an input buffer
received by a subtitle decoder consists of a timestamp (timeUs) and the subtitle data to be
decoded (data). There are four cases that can occur:
1. data contains all of the cues for the media and also their presentation timestamps.
timeUs is the time of the start of the media. The subtitle decoder receives a single input buffer.
2. data contains a single cue to be displayed at timeUs. There are no timestamps encoded in data.
The subtitle decoder receives many input buffers.
3. data contains cues covering a region of time (e.g. 5 seconds) along with their presentation
timestamps relative to the start of the region. timeUs is the time of the start of the region.
The subtitle decoder receives many input buffers.
4. As above, but the timestamps embedded in data are relative to the start of the media rather
than the start of the region. This case is tricky and best avoided.
For a side-loaded SSA file you'd have case (1).
For SSA embedded in MKV, it looks like they way it's embedded means you'd have case (2)
if you were to just pass the sample data through without changing it.
Note that timeUs is being set to blockTimeUs already.
Each region happens to be the duration of a single cue.
In the extractor, It's much easier to handle if you change the sample data so that you get case (3).
This basically means the embedded time should be 0 rather than blockTimeUs.
If you look at the SubRip case in the MKV extractor you'll see that it does exactly this.
The SubRip case also defers writing so that the end time can be set properly.
In the decoder you should create a new Subtitle instance for each decode call, rather than appending to an existing instance.
For the SSA embedded in MKV case you should end up with each call to decode producing a new Subtitle with a single cue at time 0.
The reason this works is that the event timing in a Subtitle is relative to timeUs of the buffer,
which is being set to blockTimeUs. When the decoder receives a new input buffer with a larger timeUs
than the previous one, the value passed to getCues will go down.
*/
public
class
SSADecoder
extends
SimpleSubtitleDecoder
{
private
static
final
String
TAG
=
"SSADecoder"
;
private
static
String
defaultDialogueFormat
=
"Start, End, , Layer, Style, Name, MarginL, MarginR, MarginV, Effect, Text"
;
private
static
String
defaultStyleFormat
=
"Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding"
;
private
String
[]
dialogueFormat
;
private
String
[]
styleFormat
;
private
Map
<
String
,
Style
>
styles
=
new
HashMap
<>();
public
SSADecoder
()
{
super
(
"SSADecoder"
);
dialogueFormat
=
parseKeys
(
defaultDialogueFormat
);
styleFormat
=
parseKeys
(
defaultStyleFormat
);
}
/**
* Decodes data into a {@link SSASubtitle}.
*
* @param bytes An array holding the data to be decoded, starting at position 0.
* @param length The size of the data to be decoded.
* @return The decoded {@link SSASubtitle}.
*/
@Override
protected
SSASubtitle
decode
(
byte
[]
bytes
,
int
length
)
{
SSASubtitle
subtitle
=
new
SSASubtitle
();
ParsableByteArray
data
=
new
ParsableByteArray
(
bytes
,
length
);
String
currentLine
;
while
((
currentLine
=
data
.
readLine
())
!=
null
)
{
if
(
currentLine
.
matches
(
"^Dialogue:.*$"
))
{
String
p
[]
=
currentLine
.
split
(
":"
,
2
);
Map
<
String
,
String
>
ev
=
parseLine
(
dialogueFormat
,
p
[
1
].
trim
());
subtitle
.
addEvent
(
ev
,
styles
);
}
}
return
subtitle
;
}
public
void
decodeFile
(
byte
[]
bytes
,
int
length
)
{
SSASubtitle
subtitle
=
new
SSASubtitle
();
ParsableByteArray
data
=
new
ParsableByteArray
(
bytes
,
length
);
decodeHeader
(
data
);
String
currentLine
;
while
((
currentLine
=
data
.
readLine
())
!=
null
)
{
while
(
true
)
{
currentLine
=
data
.
readLine
();
if
(
currentLine
==
null
)
break
;
Log
.
i
(
TAG
,
currentLine
);
if
(!
currentLine
.
contains
(
":"
))
break
;
String
p
[]
=
currentLine
.
split
(
":"
,
2
);
if
(
p
[
0
].
equals
(
"Format"
))
{
dialogueFormat
=
parseKeys
(
p
[
1
]);
}
else
if
(
p
[
0
].
equals
(
"Dialogue"
))
{
Map
<
String
,
String
>
ev
=
parseLine
(
dialogueFormat
,
p
[
1
].
trim
());
subtitle
.
addEvent
(
ev
,
styles
);
}
}
}
}
public
void
decodeHeader
(
byte
[]
bytes
,
int
length
)
{
ParsableByteArray
data
=
new
ParsableByteArray
(
bytes
,
length
);
decodeHeader
(
data
);
}
private
void
decodeHeader
(
ParsableByteArray
data
)
{
String
currentLine
;
while
((
currentLine
=
data
.
readLine
())
!=
null
)
{
if
(
currentLine
.
length
()
==
0
)
{
// Skip blank lines.
continue
;
}
Log
.
i
(
TAG
,
currentLine
);
if
(
currentLine
.
equals
(
"[Script Info]"
))
{
// TODO
continue
;
}
else
if
(
currentLine
.
equals
(
"[V4+ Styles]"
))
{
parseStyles
(
styles
,
data
);
continue
;
}
else
if
(
currentLine
.
equals
(
"[V4 Styles]"
))
{
parseStyles
(
styles
,
data
);
continue
;
}
else
if
(
currentLine
.
equals
(
"[Events]"
))
{
break
;
}
}
}
private
void
parseStyles
(
Map
<
String
,
Style
>
styles
,
ParsableByteArray
data
)
{
while
(
true
)
{
String
line
=
data
.
readLine
();
if
(
line
==
null
)
break
;
Log
.
i
(
TAG
,
line
);
if
(!
line
.
contains
(
":"
))
break
;
String
p
[]
=
line
.
split
(
":"
,
2
);
if
(
p
[
0
].
equals
(
"Format"
))
{
styleFormat
=
parseKeys
(
p
[
1
]);
}
else
if
(
p
[
0
].
equals
(
"Style"
))
{
Style
s
=
new
Style
(
parseLine
(
styleFormat
,
p
[
1
]));
styles
.
put
(
s
.
getName
(),
s
);
}
}
}
private
String
[]
parseKeys
(
String
format
)
{
String
keys
[]
=
format
.
split
(
", *"
);
String
r
[]
=
new
String
[
keys
.
length
];
for
(
int
i
=
0
;
i
<
r
.
length
;
i
++)
{
r
[
i
]
=
keys
[
i
].
trim
().
toLowerCase
();
}
return
r
;
}
public
static
Map
<
String
,
String
>
parseLine
(
String
[]
keys
,
String
event
)
{
Map
<
String
,
String
>
result
=
new
HashMap
<>();
String
fields
[]
=
event
.
split
(
", *"
,
keys
.
length
);
for
(
int
i
=
0
;
i
<
keys
.
length
;
i
++)
{
String
k
=
keys
[
i
];
String
v
=
fields
[
i
].
trim
();
result
.
put
(
k
,
v
);
}
return
result
;
}
public
static
void
writeMangledHeader
(
StringBuffer
s
,
byte
[]
data
){
// header contains the original format but the Matroska encoder changes this.
// we won't need anything after the [Events] line
try
{
String
header
=
new
String
(
data
,
"UTF-8"
).
split
(
"\\[Events]"
)[
0
];
s
.
append
(
header
);
}
catch
(
UnsupportedEncodingException
e
)
{
// we know this can't happen
}
s
.
append
(
"[Events]\n"
);
s
.
append
(
defaultDialogueFormat
);
s
.
append
(
"\n"
);
}
public
static
void
buildDialogue
(
StringBuffer
s
,
String
data
,
long
durationUs
)
{
s
.
append
(
"Dialogue: "
);
s
.
append
(
SSADecoder
.
formatTimeCode
(
0
));
// blockTimeUs
s
.
append
(
","
);
long
endUs
=
durationUs
;
// + blockTimeUs
if
(
endUs
==
C
.
TIME_UNSET
)
{
endUs
=
2000000
;
// 2 second default duration
}
s
.
append
(
SSADecoder
.
formatTimeCode
(
endUs
));
s
.
append
(
","
);
s
.
append
(
data
);
s
.
append
(
"\n"
);
}
public
static
String
formatTimeCode
(
long
tc_us
)
{
long
seconds
=
tc_us
/
1000000
;
long
us
=
tc_us
-
1000000
*
seconds
;
long
minutes
=
seconds
/
60
;
seconds
-=
60
*
minutes
;
long
hours
=
minutes
/
60
;
minutes
-=
60
*
hours
;
double
sec
=
seconds
+
((
float
)
us
)/
1000000.0
;
return
String
.
format
(
"%01d:%02d:%06.3f"
,
hours
,
minutes
,
sec
);
}
public
static
long
parseTimecode
(
String
time
)
{
String
p
[]
=
time
.
split
(
":"
);
long
hours
=
Long
.
parseLong
(
p
[
0
]);
long
minutes
=
Long
.
parseLong
(
p
[
1
]);
float
seconds
=
Float
.
parseFloat
(
p
[
2
]);
float
us
=
1000000
*
seconds
;
long
lus
=
((
long
)
us
);
return
lus
+
1000000
*
(
60
*
(
minutes
+
60
*
hours
));
}
}
library/src/main/java/com/google/android/exoplayer2/text/ssa/SSASubtitle.java
0 → 100644
View file @
246a0dc8
package
com
.
google
.
android
.
exoplayer2
.
text
.
ssa
;
import
android.text.Layout
;
import
android.util.Log
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.text.Cue
;
import
com.google.android.exoplayer2.text.Subtitle
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.LongArray
;
import
com.google.android.exoplayer2.util.Util
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Map
;
import
static
android
.
R
.
attr
.
start
;
/**
* Created by cablej01 on 26/12/2016.
*/
public
class
SSASubtitle
implements
Subtitle
{
private
List
<
Cue
>
cues
=
new
ArrayList
<>();
private
List
<
Long
>
cueTimesUs
=
new
ArrayList
<>();
public
SSASubtitle
()
{
super
();
}
public
void
add
(
int
pos
,
Cue
cue
,
long
cueTimeUs
)
{
cues
.
add
(
pos
,
cue
);
cueTimesUs
.
add
(
pos
,
cueTimeUs
);
}
@Override
public
int
getNextEventTimeIndex
(
long
timeUs
)
{
int
index
=
Util
.
binarySearchCeil
(
cueTimesUs
,
timeUs
,
false
,
false
);
return
index
<
cueTimesUs
.
size
()
?
index
:
C
.
INDEX_UNSET
;
}
@Override
public
int
getEventTimeCount
()
{
return
cueTimesUs
.
size
();
}
@Override
public
long
getEventTime
(
int
index
)
{
Assertions
.
checkArgument
(
index
>=
0
);
Assertions
.
checkArgument
(
index
<
cueTimesUs
.
size
());
return
cueTimesUs
.
get
(
index
);
}
@Override
public
List
<
Cue
>
getCues
(
long
timeUs
)
{
Log
.
i
(
"getCues"
,
String
.
format
(
"%d %s"
,
timeUs
,
SSADecoder
.
formatTimeCode
(
timeUs
)));
int
index
=
Util
.
binarySearchFloor
(
cueTimesUs
,
timeUs
,
true
,
false
);
if
(
index
==
-
1
||
cues
.
get
(
index
)
==
null
)
{
// timeUs is earlier than the start of the first cue, or we have an empty cue.
return
Collections
.
emptyList
();
}
else
{
return
Collections
.
singletonList
(
cues
.
get
(
index
));
}
}
protected
void
addEvent
(
Map
<
String
,
String
>
ev
,
Map
<
String
,
Style
>
styles
)
{
// int readOrder = Integer.parseInt(ev.get("readorder")); ? not needed
int
marginL
=
Integer
.
parseInt
(
ev
.
get
(
"marginl"
));
int
marginR
=
Integer
.
parseInt
(
ev
.
get
(
"marginr"
));
int
marginV
=
Integer
.
parseInt
(
ev
.
get
(
"marginv"
));
String
styleName
=
ev
.
get
(
"style"
);
Style
style
=
styles
.
get
(
styleName
);
if
(
marginL
!=
0
||
marginR
!=
0
||
marginV
!=
0
)
{
style
=
new
Style
(
style
);
}
if
(
marginL
!=
0
)
{
style
.
setMarginL
(
marginL
);
}
if
(
marginR
!=
0
)
{
style
.
setMarginR
(
marginR
);
}
if
(
marginV
!=
0
)
{
style
.
setMarginV
(
marginV
);
}
int
layer
=
Integer
.
parseInt
(
ev
.
get
(
"layer"
));
String
effect
=
ev
.
get
(
"effect"
);
String
text
=
ev
.
get
(
"text"
).
replaceAll
(
"\\\\N"
,
"\n"
);
String
simpleText
=
text
.
replaceAll
(
"\\{[^{]*\\}"
,
""
);
Cue
cue
=
new
SSACue
(
text
,
style
,
layer
,
effect
);
long
start
=
SSADecoder
.
parseTimecode
(
ev
.
get
(
"start"
));
cueTimesUs
.
add
(
start
);
cues
.
add
(
cue
);
// add null cue to remove this cue after it's duration
long
end
=
SSADecoder
.
parseTimecode
(
ev
.
get
(
"end"
));
cueTimesUs
.
add
(
end
);
cues
.
add
(
null
);
}
}
library/src/main/java/com/google/android/exoplayer2/text/ssa/Style.java
0 → 100644
View file @
246a0dc8
package
com
.
google
.
android
.
exoplayer2
.
text
.
ssa
;
import
android.graphics.Outline
;
import
java.util.Map
;
import
static
android
.
os
.
Build
.
VERSION_CODES
.
M
;
/**
* Created by cablej01 on 27/12/2016.
*/
public
class
Style
{
private
String
name
;
private
String
fontName
;
private
int
fontSize
;
private
int
primaryColour
,
secondaryColour
,
outlineColour
,
backColour
;
private
boolean
bold
,
italic
,
underline
,
strikeOut
;
private
int
scaleX
,
scaleY
,
spacing
,
angle
;
private
int
borderStyle
;
private
int
outline
,
shadow
,
alignment
,
marginL
,
marginR
,
marginV
;
private
int
alphaLevel
=
0
;
private
int
encoding
;
public
Style
()
{
}
public
Style
(
Map
<
String
,
String
>
init
)
{
name
=
init
.
get
(
"name"
);
fontName
=
init
.
get
(
"fontname"
);
fontSize
=
Integer
.
parseInt
(
init
.
get
(
"fontsize"
));
primaryColour
=
parseColour
(
init
.
get
(
"primarycolour"
));
secondaryColour
=
parseColour
(
init
.
get
(
"secondarycolour"
));
outlineColour
=
parseColour
(
init
.
get
(
"outlinecolour"
));
backColour
=
parseColour
(
init
.
get
(
"backcolour"
));
bold
=
init
.
get
(
"bold"
).
equals
(
"0"
)?
false
:
true
;
italic
=
init
.
get
(
"italic"
).
equals
(
"0"
)?
false
:
true
;
underline
=
init
.
get
(
"underline"
).
equals
(
"0"
)?
false
:
true
;
strikeOut
=
init
.
get
(
"strikeout"
).
equals
(
"0"
)?
false
:
true
;
scaleX
=
Integer
.
parseInt
(
init
.
get
(
"scalex"
));
scaleY
=
Integer
.
parseInt
(
init
.
get
(
"scaley"
));
spacing
=
Integer
.
parseInt
(
init
.
get
(
"spacing"
));
angle
=
Integer
.
parseInt
(
init
.
get
(
"angle"
));
borderStyle
=
Integer
.
parseInt
(
init
.
get
(
"borderstyle"
));
outline
=
Integer
.
parseInt
(
init
.
get
(
"outline"
));
shadow
=
Integer
.
parseInt
(
init
.
get
(
"shadow"
));
alignment
=
Integer
.
parseInt
(
init
.
get
(
"alignment"
));
marginL
=
Integer
.
parseInt
(
init
.
get
(
"marginl"
));
marginR
=
Integer
.
parseInt
(
init
.
get
(
"marginr"
));
marginV
=
Integer
.
parseInt
(
init
.
get
(
"marginv"
));
if
(
init
.
containsKey
(
"alphalevel"
))
alphaLevel
=
Integer
.
parseInt
(
init
.
get
(
"alphalevel"
));
encoding
=
Integer
.
parseInt
(
init
.
get
(
"encoding"
));
}
public
Style
(
Style
aStyle
)
{
name
=
aStyle
.
name
;
fontName
=
aStyle
.
fontName
;
fontSize
=
aStyle
.
fontSize
;
primaryColour
=
aStyle
.
primaryColour
;
secondaryColour
=
aStyle
.
secondaryColour
;
outlineColour
=
aStyle
.
outlineColour
;
backColour
=
aStyle
.
backColour
;
bold
=
aStyle
.
bold
;
italic
=
aStyle
.
italic
;
underline
=
aStyle
.
underline
;
strikeOut
=
aStyle
.
strikeOut
;
scaleX
=
aStyle
.
scaleX
;
scaleY
=
aStyle
.
scaleY
;
spacing
=
aStyle
.
spacing
;
angle
=
aStyle
.
angle
;
borderStyle
=
aStyle
.
borderStyle
;
outline
=
aStyle
.
outline
;
shadow
=
aStyle
.
shadow
;
alignment
=
aStyle
.
alignment
;
marginL
=
aStyle
.
marginL
;
marginR
=
aStyle
.
marginR
;
marginV
=
aStyle
.
marginV
;
alphaLevel
=
aStyle
.
alphaLevel
;
encoding
=
aStyle
.
encoding
;
}
public
static
int
parseColour
(
String
val
)
{
return
Integer
.
parseInt
(
val
.
substring
(
2
),
16
);
}
public
static
String
formatColour
(
int
val
)
{
return
String
.
format
(
"&H%06X"
,
val
);
}
public
String
getName
()
{
return
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
public
String
getFontName
()
{
return
fontName
;
}
public
void
setFontName
(
String
fontName
)
{
this
.
fontName
=
fontName
;
}
public
int
getFontSize
()
{
return
fontSize
;
}
public
void
setFontSize
(
int
fontSize
)
{
this
.
fontSize
=
fontSize
;
}
public
int
getPrimaryColour
()
{
return
primaryColour
;
}
public
void
setPrimaryColour
(
int
primaryColour
)
{
this
.
primaryColour
=
primaryColour
;
}
public
int
getSecondaryColour
()
{
return
secondaryColour
;
}
public
void
setSecondaryColour
(
int
secondaryColour
)
{
this
.
secondaryColour
=
secondaryColour
;
}
public
int
getOutlineColour
()
{
return
outlineColour
;
}
public
void
setOutlineColour
(
int
outlineColour
)
{
this
.
outlineColour
=
outlineColour
;
}
public
int
getBackColour
()
{
return
backColour
;
}
public
void
setBackColour
(
int
backColour
)
{
this
.
backColour
=
backColour
;
}
public
boolean
isBold
()
{
return
bold
;
}
public
void
setBold
(
boolean
bold
)
{
this
.
bold
=
bold
;
}
public
boolean
isItalic
()
{
return
italic
;
}
public
void
setItalic
(
boolean
italic
)
{
this
.
italic
=
italic
;
}
public
boolean
isUnderline
()
{
return
underline
;
}
public
void
setUnderline
(
boolean
underline
)
{
this
.
underline
=
underline
;
}
public
boolean
isStrikeOut
()
{
return
strikeOut
;
}
public
void
setStrikeOut
(
boolean
strikeOut
)
{
this
.
strikeOut
=
strikeOut
;
}
public
int
getScaleX
()
{
return
scaleX
;
}
public
void
setScaleX
(
int
scaleX
)
{
this
.
scaleX
=
scaleX
;
}
public
int
getScaleY
()
{
return
scaleY
;
}
public
void
setScaleY
(
int
scaleY
)
{
this
.
scaleY
=
scaleY
;
}
public
int
getSpacing
()
{
return
spacing
;
}
public
void
setSpacing
(
int
spacing
)
{
this
.
spacing
=
spacing
;
}
public
int
getAngle
()
{
return
angle
;
}
public
void
setAngle
(
int
angle
)
{
this
.
angle
=
angle
;
}
public
int
getBorderStyle
()
{
return
borderStyle
;
}
public
void
setBorderStyle
(
int
borderStyle
)
{
this
.
borderStyle
=
borderStyle
;
}
public
int
getOutline
()
{
return
outline
;
}
public
void
setOutline
(
int
outline
)
{
this
.
outline
=
outline
;
}
public
int
getShadow
()
{
return
shadow
;
}
public
void
setShadow
(
int
shadow
)
{
this
.
shadow
=
shadow
;
}
public
int
getAlignment
()
{
return
alignment
;
}
public
void
setAlignment
(
int
alignment
)
{
this
.
alignment
=
alignment
;
}
public
int
getMarginL
()
{
return
marginL
;
}
public
void
setMarginL
(
int
marginL
)
{
this
.
marginL
=
marginL
;
}
public
int
getMarginR
()
{
return
marginR
;
}
public
void
setMarginR
(
int
marginR
)
{
this
.
marginR
=
marginR
;
}
public
int
getMarginV
()
{
return
marginV
;
}
public
void
setMarginV
(
int
marginV
)
{
this
.
marginV
=
marginV
;
}
public
int
getAlphaLevel
()
{
return
alphaLevel
;
}
public
void
setAlphaLevel
(
int
alphaLevel
)
{
this
.
alphaLevel
=
alphaLevel
;
}
public
int
getEncoding
()
{
return
encoding
;
}
public
void
setEncoding
(
int
encoding
)
{
this
.
encoding
=
encoding
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment